OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" | 5 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <linux/input.h> | 9 #include <linux/input.h> |
10 #include <poll.h> | 10 #include <poll.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/message_loop/message_loop.h" | 22 #include "base/message_loop/message_loop.h" |
23 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
24 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
25 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
26 #include "ui/events/devices/device_data_manager.h" | 26 #include "ui/events/devices/device_data_manager.h" |
27 #include "ui/events/devices/device_util_linux.h" | 27 #include "ui/events/devices/device_util_linux.h" |
28 #include "ui/events/event.h" | 28 #include "ui/events/event.h" |
29 #include "ui/events/event_constants.h" | 29 #include "ui/events/event_constants.h" |
30 #include "ui/events/event_switches.h" | 30 #include "ui/events/event_switches.h" |
31 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" | 31 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
| 32 #include "ui/events/ozone/evdev/touch_evdev_types.h" |
| 33 #include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h" |
32 | 34 |
33 namespace { | 35 namespace { |
34 | 36 |
35 struct TouchCalibration { | 37 struct TouchCalibration { |
36 int bezel_left; | 38 int bezel_left; |
37 int bezel_right; | 39 int bezel_right; |
38 int bezel_top; | 40 int bezel_top; |
39 int bezel_bottom; | 41 int bezel_bottom; |
40 }; | 42 }; |
41 | 43 |
(...skipping 10 matching lines...) Expand all Loading... |
52 DLOG(ERROR) << "Incorrect top border calibration value passed."; | 54 DLOG(ERROR) << "Incorrect top border calibration value passed."; |
53 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) | 55 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) |
54 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | 56 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; |
55 } | 57 } |
56 } | 58 } |
57 | 59 |
58 } // namespace | 60 } // namespace |
59 | 61 |
60 namespace ui { | 62 namespace ui { |
61 | 63 |
62 TouchEventConverterEvdev::InProgressEvents::InProgressEvents() | |
63 : altered_(false), | |
64 x_(0), | |
65 y_(0), | |
66 id_(-1), | |
67 finger_(-1), | |
68 type_(ET_UNKNOWN), | |
69 radius_x_(0), | |
70 radius_y_(0), | |
71 pressure_(0) { | |
72 } | |
73 | |
74 TouchEventConverterEvdev::TouchEventConverterEvdev( | 64 TouchEventConverterEvdev::TouchEventConverterEvdev( |
75 int fd, | 65 int fd, |
76 base::FilePath path, | 66 base::FilePath path, |
77 int id, | 67 int id, |
78 InputDeviceType type, | 68 InputDeviceType type, |
79 DeviceEventDispatcherEvdev* dispatcher) | 69 DeviceEventDispatcherEvdev* dispatcher) |
80 : EventConverterEvdev(fd, path, id, type), | 70 : EventConverterEvdev(fd, path, id, type), |
81 dispatcher_(dispatcher), | 71 dispatcher_(dispatcher), |
82 syn_dropped_(false), | 72 syn_dropped_(false), |
83 is_type_a_(false), | |
84 touch_points_(0), | 73 touch_points_(0), |
85 current_slot_(0) { | 74 current_slot_(0) { |
| 75 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 76 switches::kExtraTouchNoiseFiltering)) { |
| 77 touch_noise_finder_.reset(new TouchNoiseFinder); |
| 78 } |
86 } | 79 } |
87 | 80 |
88 TouchEventConverterEvdev::~TouchEventConverterEvdev() { | 81 TouchEventConverterEvdev::~TouchEventConverterEvdev() { |
89 Stop(); | 82 Stop(); |
90 close(fd_); | 83 close(fd_); |
91 } | 84 } |
92 | 85 |
93 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { | 86 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
94 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); | 87 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); |
95 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); | 88 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); |
96 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); | 89 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); |
97 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; | 90 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; |
98 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); | 91 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); |
99 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; | 92 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; |
100 touch_points_ = | 93 touch_points_ = |
101 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, MAX_FINGERS); | 94 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); |
102 | 95 |
103 // Apply --touch-calibration. | 96 // Apply --touch-calibration. |
104 if (type() == INPUT_DEVICE_INTERNAL) { | 97 if (type() == INPUT_DEVICE_INTERNAL) { |
105 TouchCalibration cal = {}; | 98 TouchCalibration cal = {}; |
106 GetTouchCalibration(&cal); | 99 GetTouchCalibration(&cal); |
107 x_min_tuxels_ += cal.bezel_left; | 100 x_min_tuxels_ += cal.bezel_left; |
108 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; | 101 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; |
109 y_min_tuxels_ += cal.bezel_top; | 102 y_min_tuxels_ += cal.bezel_top; |
110 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; | 103 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; |
111 | 104 |
112 VLOG(1) << "applying touch calibration: " | 105 VLOG(1) << "applying touch calibration: " |
113 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, | 106 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, |
114 cal.bezel_right, cal.bezel_top, | 107 cal.bezel_right, cal.bezel_top, |
115 cal.bezel_bottom); | 108 cal.bezel_bottom); |
116 } | 109 } |
117 | 110 |
118 events_.resize(touch_points_); | 111 events_.resize(touch_points_); |
119 for (size_t i = 0; i < events_.size(); ++i) { | 112 for (size_t i = 0; i < events_.size(); ++i) { |
120 events_[i].finger_ = info.GetSlotValue(ABS_MT_TRACKING_ID, i); | 113 events_[i].x = info.GetSlotValue(ABS_MT_POSITION_X, i); |
121 events_[i].type_ = | 114 events_[i].y = info.GetSlotValue(ABS_MT_POSITION_Y, i); |
122 events_[i].finger_ < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; | 115 events_[i].tracking_id = info.GetSlotValue(ABS_MT_TRACKING_ID, i); |
123 events_[i].x_ = info.GetSlotValue(ABS_MT_POSITION_X, i); | 116 events_[i].touching = (events_[i].tracking_id >= 0); |
124 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); | 117 events_[i].slot = i; |
125 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); | 118 events_[i].radius_x = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); |
126 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); | 119 events_[i].radius_y = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); |
127 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); | 120 events_[i].pressure = info.GetSlotValue(ABS_MT_PRESSURE, i); |
128 } | 121 } |
129 } | 122 } |
130 | 123 |
131 bool TouchEventConverterEvdev::Reinitialize() { | 124 bool TouchEventConverterEvdev::Reinitialize() { |
132 EventDeviceInfo info; | 125 EventDeviceInfo info; |
133 if (info.Initialize(fd_)) { | 126 if (info.Initialize(fd_)) { |
134 Initialize(info); | 127 Initialize(info); |
135 return true; | 128 return true; |
136 } | 129 } |
137 return false; | 130 return false; |
138 } | 131 } |
139 | 132 |
140 bool TouchEventConverterEvdev::HasTouchscreen() const { | 133 bool TouchEventConverterEvdev::HasTouchscreen() const { |
141 return true; | 134 return true; |
142 } | 135 } |
143 | 136 |
144 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { | 137 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
145 return gfx::Size(x_num_tuxels_, y_num_tuxels_); | 138 return gfx::Size(x_num_tuxels_, y_num_tuxels_); |
146 } | 139 } |
147 | 140 |
148 int TouchEventConverterEvdev::GetTouchPoints() const { | 141 int TouchEventConverterEvdev::GetTouchPoints() const { |
149 return touch_points_; | 142 return touch_points_; |
150 } | 143 } |
151 | 144 |
152 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 145 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
153 input_event inputs[MAX_FINGERS * 6 + 1]; | 146 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; |
154 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 147 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
155 if (read_size < 0) { | 148 if (read_size < 0) { |
156 if (errno == EINTR || errno == EAGAIN) | 149 if (errno == EINTR || errno == EAGAIN) |
157 return; | 150 return; |
158 if (errno != ENODEV) | 151 if (errno != ENODEV) |
159 PLOG(ERROR) << "error reading device " << path_.value(); | 152 PLOG(ERROR) << "error reading device " << path_.value(); |
160 Stop(); | 153 Stop(); |
161 return; | 154 return; |
162 } | 155 } |
163 | 156 |
164 if (ignore_events_) | 157 if (ignore_events_) |
165 return; | 158 return; |
166 | 159 |
167 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { | 160 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { |
168 ProcessInputEvent(inputs[i]); | 161 ProcessInputEvent(inputs[i]); |
169 } | 162 } |
170 } | 163 } |
171 | 164 |
172 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { | 165 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { |
173 if (input.type == EV_SYN) { | 166 if (input.type == EV_SYN) { |
174 ProcessSyn(input); | 167 ProcessSyn(input); |
175 } else if(syn_dropped_) { | 168 } else if (syn_dropped_) { |
176 // Do nothing. This branch indicates we have lost sync with the driver. | 169 // Do nothing. This branch indicates we have lost sync with the driver. |
177 } else if (input.type == EV_ABS) { | 170 } else if (input.type == EV_ABS) { |
178 if (events_.size() <= current_slot_) { | 171 if (events_.size() <= current_slot_) { |
179 LOG(ERROR) << "current_slot_ (" << current_slot_ | 172 LOG(ERROR) << "current_slot_ (" << current_slot_ |
180 << ") >= events_.size() (" << events_.size() << ")"; | 173 << ") >= events_.size() (" << events_.size() << ")"; |
181 } else { | 174 } else { |
182 ProcessAbs(input); | 175 ProcessAbs(input); |
183 } | 176 } |
184 } else if (input.type == EV_KEY) { | 177 } else if (input.type == EV_KEY) { |
185 switch (input.code) { | 178 switch (input.code) { |
186 case BTN_TOUCH: | 179 case BTN_TOUCH: |
187 break; | 180 break; |
188 default: | 181 default: |
189 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 182 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
190 } | 183 } |
191 } else { | 184 } else { |
192 NOTIMPLEMENTED() << "invalid type: " << input.type; | 185 NOTIMPLEMENTED() << "invalid type: " << input.type; |
193 } | 186 } |
194 } | 187 } |
195 | 188 |
196 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { | 189 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
197 switch (input.code) { | 190 switch (input.code) { |
198 case ABS_MT_TOUCH_MAJOR: | 191 case ABS_MT_TOUCH_MAJOR: |
199 // TODO(spang): If we have all of major, minor, and orientation, | 192 // TODO(spang): If we have all of major, minor, and orientation, |
200 // we can scale the ellipse correctly. However on the Pixel we get | 193 // we can scale the ellipse correctly. However on the Pixel we get |
201 // neither minor nor orientation, so this is all we can do. | 194 // neither minor nor orientation, so this is all we can do. |
202 events_[current_slot_].radius_x_ = input.value / 2.0f; | 195 events_[current_slot_].radius_x = input.value / 2.0f; |
203 break; | 196 break; |
204 case ABS_MT_TOUCH_MINOR: | 197 case ABS_MT_TOUCH_MINOR: |
205 events_[current_slot_].radius_y_ = input.value / 2.0f; | 198 events_[current_slot_].radius_y = input.value / 2.0f; |
206 break; | 199 break; |
207 case ABS_MT_POSITION_X: | 200 case ABS_MT_POSITION_X: |
208 events_[current_slot_].x_ = input.value; | 201 events_[current_slot_].x = input.value; |
209 break; | 202 break; |
210 case ABS_MT_POSITION_Y: | 203 case ABS_MT_POSITION_Y: |
211 events_[current_slot_].y_ = input.value; | 204 events_[current_slot_].y = input.value; |
212 break; | 205 break; |
213 case ABS_MT_TRACKING_ID: | 206 case ABS_MT_TRACKING_ID: |
214 if (input.value < 0) { | 207 if (input.value < 0) { |
215 events_[current_slot_].type_ = ET_TOUCH_RELEASED; | 208 events_[current_slot_].touching = false; |
216 } else { | 209 } else { |
217 events_[current_slot_].finger_ = input.value; | 210 events_[current_slot_].touching = true; |
218 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | 211 events_[current_slot_].cancelled = false; |
219 } | 212 } |
| 213 events_[current_slot_].tracking_id = input.value; |
220 break; | 214 break; |
221 case ABS_MT_PRESSURE: | 215 case ABS_MT_PRESSURE: |
222 events_[current_slot_].pressure_ = input.value - pressure_min_; | 216 events_[current_slot_].pressure = input.value - pressure_min_; |
223 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; | 217 events_[current_slot_].pressure /= pressure_max_ - pressure_min_; |
224 break; | 218 break; |
225 case ABS_MT_SLOT: | 219 case ABS_MT_SLOT: |
226 if (input.value >= 0 && | 220 if (input.value >= 0 && |
227 static_cast<size_t>(input.value) < events_.size()) { | 221 static_cast<size_t>(input.value) < events_.size()) { |
228 current_slot_ = input.value; | 222 current_slot_ = input.value; |
229 } else { | 223 } else { |
230 LOG(ERROR) << "invalid touch event index: " << input.value; | 224 LOG(ERROR) << "invalid touch event index: " << input.value; |
231 return; | 225 return; |
232 } | 226 } |
233 break; | 227 break; |
234 default: | 228 default: |
235 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; | 229 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; |
236 return; | 230 return; |
237 } | 231 } |
238 events_[current_slot_].altered_ = true; | 232 events_[current_slot_].altered = true; |
239 } | 233 } |
240 | 234 |
241 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { | 235 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { |
242 switch (input.code) { | 236 switch (input.code) { |
243 case SYN_REPORT: | 237 case SYN_REPORT: |
244 if (syn_dropped_) { | 238 if (syn_dropped_) { |
245 // Have to re-initialize. | 239 // Have to re-initialize. |
246 if (Reinitialize()) { | 240 if (Reinitialize()) { |
247 syn_dropped_ = false; | 241 syn_dropped_ = false; |
248 for(InProgressEvents& event: events_) | 242 for(InProgressTouchEvdev& event : events_) |
249 event.altered_ = false; | 243 event.altered = false; |
250 } else { | 244 } else { |
251 LOG(ERROR) << "failed to re-initialize device info"; | 245 LOG(ERROR) << "failed to re-initialize device info"; |
252 } | 246 } |
253 } else { | 247 } else { |
254 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); | 248 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); |
255 } | 249 } |
256 if (is_type_a_) | |
257 current_slot_ = 0; | |
258 break; | |
259 case SYN_MT_REPORT: | |
260 // For type A devices, we just get a stream of all current contacts, | |
261 // in some arbitrary order. | |
262 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | |
263 if (events_.size() - 1 > current_slot_) | |
264 current_slot_++; | |
265 is_type_a_ = true; | |
266 break; | 250 break; |
267 case SYN_DROPPED: | 251 case SYN_DROPPED: |
268 // Some buffer has overrun. We ignore all events up to and | 252 // Some buffer has overrun. We ignore all events up to and |
269 // including the next SYN_REPORT. | 253 // including the next SYN_REPORT. |
270 syn_dropped_ = true; | 254 syn_dropped_ = true; |
271 break; | 255 break; |
272 default: | 256 default: |
273 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; | 257 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; |
274 } | 258 } |
275 } | 259 } |
276 | 260 |
277 void TouchEventConverterEvdev::ReportEvent(int touch_id, | 261 EventType TouchEventConverterEvdev::GetEventTypeForTouch( |
278 const InProgressEvents& event, | 262 const InProgressTouchEvdev& touch) { |
| 263 if (touch.cancelled) |
| 264 return ET_UNKNOWN; |
| 265 |
| 266 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { |
| 267 if (touch.touching && !touch.was_touching) |
| 268 return ET_UNKNOWN; |
| 269 return ET_TOUCH_CANCELLED; |
| 270 } |
| 271 |
| 272 if (touch.touching) |
| 273 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; |
| 274 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; |
| 275 } |
| 276 |
| 277 void TouchEventConverterEvdev::ReportEvent(const InProgressTouchEvdev& event, |
| 278 EventType event_type, |
279 const base::TimeDelta& timestamp) { | 279 const base::TimeDelta& timestamp) { |
280 dispatcher_->DispatchTouchEvent(TouchEventParams( | 280 dispatcher_->DispatchTouchEvent(TouchEventParams( |
281 id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), | 281 id_, event.slot, event_type, gfx::PointF(event.x, event.y), |
282 gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, | 282 gfx::Vector2dF(event.radius_x, event.radius_y), event.pressure, |
283 timestamp)); | 283 timestamp)); |
284 } | 284 } |
285 | 285 |
286 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { | 286 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { |
| 287 if (touch_noise_finder_) |
| 288 touch_noise_finder_->HandleTouches(events_, delta); |
| 289 |
287 for (size_t i = 0; i < events_.size(); i++) { | 290 for (size_t i = 0; i < events_.size(); i++) { |
288 if (events_[i].altered_) { | 291 InProgressTouchEvdev* event = &events_[i]; |
289 ReportEvent(i, events_[i], delta); | 292 if (!event->altered) |
| 293 continue; |
290 | 294 |
291 // Subsequent events for this finger will be touch-move until it | 295 EventType event_type = GetEventTypeForTouch(*event); |
292 // is released. | 296 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) |
293 events_[i].type_ = ET_TOUCH_MOVED; | 297 event->cancelled = true; |
294 events_[i].altered_ = false; | 298 |
295 } | 299 if (event_type != ET_UNKNOWN) |
| 300 ReportEvent(*event, event_type, delta); |
| 301 |
| 302 event->was_touching = event->touching; |
| 303 event->altered = false; |
296 } | 304 } |
297 } | 305 } |
298 | 306 |
299 } // namespace ui | 307 } // namespace ui |
OLD | NEW |