summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspang <spang@chromium.org>2015-06-11 11:24:35 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-11 18:25:08 +0000
commitfd6b78bc2cac155f67f0bd09c184645353f7d6b9 (patch)
tree614b19ef6541a0df2af8e137e3e8b8dc4f873d93
parent79e2c2139c83ccc50de4a73288eac94ab13b94f0 (diff)
downloadchromium_src-fd6b78bc2cac155f67f0bd09c184645353f7d6b9.zip
chromium_src-fd6b78bc2cac155f67f0bd09c184645353f7d6b9.tar.gz
chromium_src-fd6b78bc2cac155f67f0bd09c184645353f7d6b9.tar.bz2
ozone: evdev: Add quirk to allow BTN_LEFT for single touch touchscreens
This restores support for some older USB touchscreens that use the mouse HID usage class and use mouse button events to represent touches. Left clicks are converted to touch events, and although some devices support right clicks these are ignored. BUG=477695 TEST=Plug Elo TouchSystems 2700 into Chrome OS. Touch works. Review URL: https://codereview.chromium.org/1179623002 Cr-Commit-Position: refs/heads/master@{#333992}
-rw-r--r--ui/events/ozone/evdev/event_device_info.cc2
-rw-r--r--ui/events/ozone/evdev/event_device_info_unittest.cc12
-rw-r--r--ui/events/ozone/evdev/event_device_test_util.cc30
-rw-r--r--ui/events/ozone/evdev/event_device_test_util.h1
-rw-r--r--ui/events/ozone/evdev/touch_event_converter_evdev.cc22
-rw-r--r--ui/events/ozone/evdev/touch_event_converter_evdev.h3
-rw-r--r--ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc92
7 files changed, 155 insertions, 7 deletions
diff --git a/ui/events/ozone/evdev/event_device_info.cc b/ui/events/ozone/evdev/event_device_info.cc
index e3c9f73..fba26d3 100644
--- a/ui/events/ozone/evdev/event_device_info.cc
+++ b/ui/events/ozone/evdev/event_device_info.cc
@@ -411,7 +411,7 @@ EventDeviceInfo::ProbeLegacyAbsoluteDevice() const {
if (HasKeyEvent(BTN_TOOL_FINGER) && HasKeyEvent(BTN_TOUCH))
return LegacyAbsoluteDeviceType::LADT_TOUCHPAD;
- if (HasKeyEvent(BTN_TOUCH))
+ if (HasKeyEvent(BTN_TOUCH) || HasKeyEvent(BTN_LEFT))
return LegacyAbsoluteDeviceType::LADT_TOUCHSCREEN;
return LegacyAbsoluteDeviceType::LADT_NONE;
diff --git a/ui/events/ozone/evdev/event_device_info_unittest.cc b/ui/events/ozone/evdev/event_device_info_unittest.cc
index cc7af80..63187a1 100644
--- a/ui/events/ozone/evdev/event_device_info_unittest.cc
+++ b/ui/events/ozone/evdev/event_device_info_unittest.cc
@@ -136,4 +136,16 @@ TEST_F(EventDeviceInfoTest, HybridKeyboardWithMouse) {
EXPECT_FALSE(devinfo.HasTablet());
}
+TEST_F(EventDeviceInfoTest, AbsoluteMouseTouchscreen) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kElo_TouchSystems_2700, &devinfo));
+
+ // This touchscreen uses BTN_LEFT for touch contact.
+ EXPECT_FALSE(devinfo.HasKeyboard());
+ EXPECT_FALSE(devinfo.HasMouse());
+ EXPECT_FALSE(devinfo.HasTouchpad());
+ EXPECT_TRUE(devinfo.HasTouchscreen());
+ EXPECT_FALSE(devinfo.HasTablet());
+}
+
} // namespace ui
diff --git a/ui/events/ozone/evdev/event_device_test_util.cc b/ui/events/ozone/evdev/event_device_test_util.cc
index cb4116c..4d5407c 100644
--- a/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/ui/events/ozone/evdev/event_device_test_util.cc
@@ -363,6 +363,36 @@ const DeviceCapabilities kLogitechTouchKeyboardK400 = {
arraysize(kLogitechTouchKeyboardK400AbsAxes),
};
+// Captured from Elo TouchSystems 2700 touchscreen.
+const DeviceAbsoluteAxis kElo_TouchSystems_2700AbsAxes[] = {
+ {ABS_X, {0, 0, 4095, 0, 0, 0}},
+ {ABS_Y, {0, 0, 4095, 0, 0, 0}},
+ {ABS_MISC, {0, 0, 256, 0, 0, 0}},
+};
+const DeviceCapabilities kElo_TouchSystems_2700 = {
+ /* path */ "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/"
+ "input/input9/event9",
+ /* name */ "Elo TouchSystems, Inc. Elo TouchSystems 2700 IntelliTouch(r) "
+ "USB Touchmonitor Interface",
+ /* phys */ "usb-0000:00:1d.0-1.3/input0",
+ /* uniq */ "20A01347",
+ /* bustype */ "0003",
+ /* vendor */ "04e7",
+ /* product */ "0020",
+ /* version */ "0100",
+ /* prop */ "0",
+ /* ev */ "1b",
+ /* key */ "10000 0 0 0 0",
+ /* rel */ "0",
+ /* abs */ "10000000003",
+ /* msc */ "10",
+ /* sw */ "0",
+ /* led */ "0",
+ /* ff */ "0",
+ kElo_TouchSystems_2700AbsAxes,
+ arraysize(kElo_TouchSystems_2700AbsAxes),
+};
+
bool CapabilitiesToDeviceInfo(const DeviceCapabilities& capabilities,
EventDeviceInfo* devinfo) {
std::vector<unsigned long> ev_bits;
diff --git a/ui/events/ozone/evdev/event_device_test_util.h b/ui/events/ozone/evdev/event_device_test_util.h
index 46afb6a..b02f74a 100644
--- a/ui/events/ozone/evdev/event_device_test_util.h
+++ b/ui/events/ozone/evdev/event_device_test_util.h
@@ -68,6 +68,7 @@ extern const DeviceCapabilities kMimoTouch2Touchscreen;
extern const DeviceCapabilities kWacomIntuosPtS_Pen;
extern const DeviceCapabilities kWacomIntuosPtS_Finger;
extern const DeviceCapabilities kLogitechTouchKeyboardK400;
+extern const DeviceCapabilities kElo_TouchSystems_2700;
} // namspace ui
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index 2427f89..a5e9c19 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -137,6 +137,9 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
current_slot_ = 0;
}
+ quirk_left_mouse_button_ =
+ !has_mt_ && !info.HasKeyEvent(BTN_TOUCH) && info.HasKeyEvent(BTN_LEFT);
+
// Apply --touch-calibration.
if (type() == INPUT_DEVICE_INTERNAL) {
TouchCalibration cal = {};
@@ -178,6 +181,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
}
} else {
// TODO(spang): Add key state to EventDeviceInfo to allow initial contact.
+ // (and make sure to take into account quirk_left_mouse_button_)
events_[0].x = 0;
events_[0].y = 0;
events_[0].tracking_id = kTrackingIdForUnusedSlot;
@@ -259,6 +263,8 @@ void TouchEventConverterEvdev::ProcessMultitouchEvent(
}
} else if (input.type == EV_KEY) {
ProcessKey(input);
+ } else if (input.type == EV_MSC) {
+ // Ignored.
} else {
NOTIMPLEMENTED() << "invalid type: " << input.type;
}
@@ -272,18 +278,22 @@ void TouchEventConverterEvdev::EmulateMultitouchEvent(
emulated_event.code = AbsCodeToMtCode(event.code);
if (emulated_event.code >= 0)
ProcessMultitouchEvent(emulated_event);
- } else if (event.type == EV_KEY && event.code == BTN_TOUCH) {
- emulated_event.type = EV_ABS;
- emulated_event.code = ABS_MT_TRACKING_ID;
- emulated_event.value =
- event.value ? NextTrackingId() : kTrackingIdForUnusedSlot;
- ProcessMultitouchEvent(emulated_event);
+ } else if (event.type == EV_KEY) {
+ if (event.code == BTN_TOUCH ||
+ (quirk_left_mouse_button_ && event.code == BTN_LEFT)) {
+ emulated_event.type = EV_ABS;
+ emulated_event.code = ABS_MT_TRACKING_ID;
+ emulated_event.value =
+ event.value ? NextTrackingId() : kTrackingIdForUnusedSlot;
+ ProcessMultitouchEvent(emulated_event);
+ }
}
}
void TouchEventConverterEvdev::ProcessKey(const input_event& input) {
switch (input.code) {
case BTN_TOUCH:
+ case BTN_LEFT:
break;
default:
NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code;
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.h b/ui/events/ozone/evdev/touch_event_converter_evdev.h
index 7cd7576..edddea6 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev.h
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev.h
@@ -83,6 +83,9 @@ class EVENTS_OZONE_EVDEV_EXPORT TouchEventConverterEvdev
// Device has multitouch capability.
bool has_mt_;
+ // Use BTN_LEFT instead of BT_TOUCH.
+ bool quirk_left_mouse_button_ = false;
+
// Pressure values.
int pressure_min_;
int pressure_max_; // Used to normalize pressure values.
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 77eeef6..96a1f32 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -47,6 +47,12 @@ void InitPixelTouchscreen(TouchEventConverterEvdev* device) {
device->Initialize(devinfo);
}
+void InitEloTouchscreen(TouchEventConverterEvdev* device) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kElo_TouchSystems_2700, &devinfo));
+ device->Initialize(devinfo);
+}
+
} // namespace
class MockTouchEventConverterEvdev : public TouchEventConverterEvdev {
@@ -541,6 +547,92 @@ TEST_F(TouchEventConverterEvdevTest, ShouldReleaseContactsOnStop) {
EXPECT_EQ(0, ev2.slot);
}
+// crbug.com/477695
+TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
+ ui::MockTouchEventConverterEvdev* dev = device();
+
+ InitEloTouchscreen(dev);
+
+ // Captured from Elo TouchSystems 2700.
+ timeval time;
+ time = {1433965490, 837958};
+ struct input_event mock_kernel_queue_press[] = {
+ {time, EV_ABS, ABS_X, 3654},
+ {time, EV_ABS, ABS_Y, 1054},
+ {time, EV_ABS, ABS_MISC, 18},
+ {time, EV_SYN, SYN_REPORT, 0},
+
+ {time, EV_MSC, MSC_SCAN, 90001},
+ {time, EV_KEY, BTN_LEFT, 1},
+ {time, EV_ABS, ABS_Y, 1055},
+ {time, EV_ABS, ABS_MISC, 25},
+ {time, EV_SYN, SYN_REPORT, 0},
+ };
+ time = {1433965491, 1953};
+ struct input_event mock_kernel_queue_move[] = {
+ {time, EV_ABS, ABS_X, 3644},
+ {time, EV_ABS, ABS_Y, 1059},
+ {time, EV_ABS, ABS_MISC, 36},
+ {time, EV_SYN, SYN_REPORT, 0},
+ };
+ time = {1433965491, 225959};
+ struct input_event mock_kernel_queue_release[] = {
+ {time, EV_MSC, MSC_SCAN, 90001},
+ {time, EV_KEY, BTN_LEFT, 0},
+ {time, EV_ABS, ABS_MISC, 0},
+ {time, EV_SYN, SYN_REPORT, 0},
+ };
+
+ // Press.
+ dev->ConfigureReadMock(mock_kernel_queue_press,
+ arraysize(mock_kernel_queue_press), 0);
+ dev->ReadNow();
+ EXPECT_EQ(1u, size());
+ ui::TouchEventParams event = dispatched_event(0);
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(1433965490837958),
+ event.timestamp);
+ EXPECT_EQ(3654, event.location.x());
+ EXPECT_EQ(1055, event.location.y());
+ EXPECT_EQ(0, event.slot);
+ EXPECT_FLOAT_EQ(0.f, event.radii.x());
+ EXPECT_FLOAT_EQ(0.f, event.pressure);
+
+ // Move.
+ dev->ConfigureReadMock(mock_kernel_queue_move,
+ arraysize(mock_kernel_queue_move), 0);
+ dev->ReadNow();
+ EXPECT_EQ(2u, size());
+ event = dispatched_event(1);
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(1433965491001953),
+ event.timestamp);
+ EXPECT_EQ(3644, event.location.x());
+ EXPECT_EQ(1059, event.location.y());
+ EXPECT_EQ(0, event.slot);
+ EXPECT_FLOAT_EQ(0.f, event.radii.x());
+ EXPECT_FLOAT_EQ(0.f, event.pressure);
+
+ // Release.
+ dev->ConfigureReadMock(mock_kernel_queue_release,
+ arraysize(mock_kernel_queue_release), 0);
+ dev->ReadNow();
+ EXPECT_EQ(3u, size());
+ event = dispatched_event(2);
+ EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(1433965491225959),
+ event.timestamp);
+ EXPECT_EQ(3644, event.location.x());
+ EXPECT_EQ(1059, event.location.y());
+ EXPECT_EQ(0, event.slot);
+ EXPECT_FLOAT_EQ(0.f, event.radii.x());
+ EXPECT_FLOAT_EQ(0.f, event.pressure);
+
+ // No dispatch on destruction.
+ DestroyDevice();
+ EXPECT_EQ(3u, size());
+}
+
// crbug.com/407386
TEST_F(TouchEventConverterEvdevTest,
DontChangeMultitouchPositionFromLegacyAxes) {