Add a minimum physical threshold for freeform gesture on touchpad
Currently, TouchInputMapper uses the product of the size of the touchpad
and a ratio (currently 0.25) to determine a two finger gesture is a
freeform gesture or a swipe, that when the distance of two pointers is
greater than the calculated value, it is a freeform gesture, otherwise,
it is a swipe gesture. However, on a really small touch pad, such as
Sony Dualshock4's, due to the common size of human fingers, almost all
two finger gestures are decided to be freeform. Adding a minimun
physical value for the freeform gesture, 30 mm, can solve the problem.
Bug: 197146318
Test: manual test
Change-Id: Ia4ff521cb2f47b587fa55a5d753b90d023a648ef
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index f07a3e8..1b0c61c 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -42,6 +42,8 @@
// data.
static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+// Minimum width between two pointers to determine a gesture as freeform gesture in mm
+static const float MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER = 30;
// --- Static Definitions ---
template <typename T>
@@ -936,6 +938,11 @@
// Raw width and height in the natural orientation.
const int32_t rawWidth = mRawPointerAxes.getRawWidth();
const int32_t rawHeight = mRawPointerAxes.getRawHeight();
+ const int32_t rawXResolution = mRawPointerAxes.x.resolution;
+ const int32_t rawYResolution = mRawPointerAxes.y.resolution;
+ // Calculate the mean resolution when both x and y resolution are set, otherwise set it to 0.
+ const float rawMeanResolution =
+ (rawXResolution > 0 && rawYResolution > 0) ? (rawXResolution + rawYResolution) / 2 : 0;
const bool viewportChanged = mViewport != *newViewport;
bool skipViewportUpdate = false;
@@ -1094,10 +1101,14 @@
mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal;
mPointerYZoomScale = mPointerXZoomScale;
- // Max width between pointers to detect a swipe gesture is more than some fraction
- // of the diagonal axis of the touch pad. Touches that are wider than this are
- // translated into freeform gestures.
- mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
+ // Calculate the min freeform gesture width. It will be 0 when the resolution of any
+ // axis is non positive value.
+ const float minFreeformGestureWidth =
+ rawMeanResolution * MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER;
+
+ mPointerGestureMaxSwipeWidth =
+ std::max(mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal,
+ minFreeformGestureWidth);
// Abort current pointer usages because the state has changed.
const nsecs_t readTime = when; // synthetic event
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 714ad3f..3042be6 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -527,7 +527,9 @@
float mPointerXZoomScale;
float mPointerYZoomScale;
- // The maximum swipe width.
+ // The maximum swipe width between pointers to detect a swipe gesture
+ // in the number of pixels.Touches that are wider than this are translated
+ // into freeform gestures.
float mPointerGestureMaxSwipeWidth;
struct PointerDistanceHeapElement {