diff options
author | spang <spang@chromium.org> | 2015-06-11 11:24:35 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-11 18:25:08 +0000 |
commit | fd6b78bc2cac155f67f0bd09c184645353f7d6b9 (patch) | |
tree | 614b19ef6541a0df2af8e137e3e8b8dc4f873d93 | |
parent | 79e2c2139c83ccc50de4a73288eac94ab13b94f0 (diff) | |
download | chromium_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}
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) { |