Fix virtual touchpad scroll events.
1. Correctly configure the uinput device to pass REL_*WHEEL events.
2. Configure the virtual touchpad as a 'rotary encoder', which is
an inputflinger device class originally provided for the G1 scroll
ball. This provides two advantages over the default mouse-wheel
interpretation:
- It works without an associated mouse pointer to determine the
event target.
- It allows for higher resolution through a scale factor (the
scaling here is chosen by experiment to feel no worse than wheel
mode, but might benefit from future adjustment).
There is one accompanying disadvantage: inputflinger only handles
vertical scrolling (REL_WHEEL) and ignores the horizontal axis
(REL_HWHEEL).
Bug: 62632827
Test: manual on sailfish
Change-Id: Ic8edad01796d75e8c94fa20f05a5badb0727a948
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index b9aa8fe..6b11ce3 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -33,9 +33,6 @@
test_static_libs = [
"libcutils",
"libvirtualtouchpad",
-]
-
-test_shared_libs = [
"libbase",
"liblog",
"libutils",
@@ -46,7 +43,6 @@
cc_test {
srcs: test_src_files,
static_libs: test_static_libs,
- shared_libs: test_shared_libs,
header_libs: header_libraries,
cppflags = [
"-std=c++11",
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index ae56bf6..251ed0e 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -28,20 +28,10 @@
static constexpr int32_t kHeight = 0x10000;
static constexpr int32_t kSlots = 2;
+static constexpr float kScrollScale = 100.0f;
+
int32_t scale_relative_scroll(float x) {
- // Guilty with an explanation, your honor.
- // Ideally we should be able to communicate the full incoming precision
- // to InputFlinger, through the evdev int32_t value, by scaling by a
- // large factor, i.e. 2²³ for IEEE single precision floating point.
- // However, although InputFlinger has |wheelVelocityControlParameters|,
- // those parameters are currently hard coded, with a scale factor of 1.0.
- // The observed evdev value for a physical mouse scroll wheel is usually
- // ±1, with higher values up to ±4 for a very fast spin. So we imitate
- // that. If the incoming value is not actually 0, the resulting magnitude
- // should be at least 1, so that small movements are not lost.
- // Adding IDC configurability of |VelocityControlParameters| may be
- // desirable in the future.
- return copysignf(ceilf(fabs(4.0f * x)), x);
+ return kScrollScale * x;
}
} // anonymous namespace
@@ -82,6 +72,8 @@
touchpad.injector->ConfigureInputProperty(INPUT_PROP_DIRECT);
touchpad.injector->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1);
touchpad.injector->ConfigureAbsSlots(kSlots);
+ touchpad.injector->ConfigureRel(REL_WHEEL);
+ touchpad.injector->ConfigureRel(REL_HWHEEL);
touchpad.injector->ConfigureKey(BTN_TOUCH);
touchpad.injector->ConfigureKey(BTN_BACK);
touchpad.injector->ConfigureEnd();
@@ -192,6 +184,7 @@
touchpad.injector->ResetError();
const int32_t scaled_x = scale_relative_scroll(x);
const int32_t scaled_y = scale_relative_scroll(y);
+ ALOGV("(%f,%f) -> (%" PRId32 ",%" PRId32 ")", x, y, scaled_x, scaled_y);
if (scaled_x) {
touchpad.injector->SendRel(REL_HWHEEL, scaled_x);
}
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc
new file mode 100644
index 0000000..205e8b9
--- /dev/null
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc
@@ -0,0 +1,26 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Virtual touchpad for the primary display
+device.internal = 1
+
+touch.deviceType = touchScreen
+
+# Have input flinger treat injected scroll events like a G1 ball
+# rather than the default mouse wheel, because the latter requires
+# a visible pointer for targeting.
+device.type = rotaryEncoder
+device.res = 1.0e+2
+device.scalingFactor = 1.0e-2
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
index 3728ef0..d9714e0 100644
--- a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
@@ -18,6 +18,13 @@
touch.deviceType = touchScreen
+# Have input flinger treat injected scroll events like a G1 ball
+# rather than the default mouse wheel, because the latter requires
+# a visible pointer for targeting.
+device.type = rotaryEncoder
+device.res = 1.0e+2
+device.scalingFactor = 1.0e-2
+
# This displayID matches the unique ID of the virtual display created for VR.
# This will indicate to input flinger than it should link this input device
# with the virtual display.
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 564bcd7..b19b018 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -169,6 +169,11 @@
expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
// From ConfigureAbsSlots(kSlots):
expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
+ // From ConfigureRel(REL_WHEEL):
+ expect.IoctlSetInt(UI_SET_EVBIT, EV_REL);
+ expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL);
+ // From ConfigureRel(REL_HWHEEL):
+ expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL);
// From ConfigureKey(BTN_TOUCH):
expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);