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 13 matching lines...) Expand all Loading... | |
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 "base/trace_event/trace_event.h" | 26 #include "base/trace_event/trace_event.h" |
27 #include "ui/events/devices/device_data_manager.h" | 27 #include "ui/events/devices/device_data_manager.h" |
28 #include "ui/events/devices/device_util_linux.h" | 28 #include "ui/events/devices/device_util_linux.h" |
29 #include "ui/events/event.h" | 29 #include "ui/events/event.h" |
30 #include "ui/events/event_constants.h" | 30 #include "ui/events/event_constants.h" |
31 #include "ui/events/event_switches.h" | 31 #include "ui/events/event_switches.h" |
32 #include "ui/events/event_utils.h" | 32 #include "ui/events/event_utils.h" |
33 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" | 33 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
34 #include "ui/events/ozone/evdev/palm_suppression_filter.h" | |
34 #include "ui/events/ozone/evdev/touch_evdev_types.h" | 35 #include "ui/events/ozone/evdev/touch_evdev_types.h" |
35 #include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h" | 36 #include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h" |
36 #include "ui/ozone/public/input_controller.h" | 37 #include "ui/ozone/public/input_controller.h" |
37 | 38 |
38 namespace { | 39 namespace { |
39 | 40 |
40 const int kMaxTrackingId = 0xffff; // TRKID_MAX in kernel. | 41 const int kMaxTrackingId = 0xffff; // TRKID_MAX in kernel. |
41 | 42 |
42 struct TouchCalibration { | 43 struct TouchCalibration { |
43 int bezel_left; | 44 int bezel_left; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 int id, | 107 int id, |
107 const EventDeviceInfo& devinfo, | 108 const EventDeviceInfo& devinfo, |
108 DeviceEventDispatcherEvdev* dispatcher) | 109 DeviceEventDispatcherEvdev* dispatcher) |
109 : EventConverterEvdev(fd, | 110 : EventConverterEvdev(fd, |
110 path, | 111 path, |
111 id, | 112 id, |
112 devinfo.device_type(), | 113 devinfo.device_type(), |
113 devinfo.name(), | 114 devinfo.name(), |
114 devinfo.vendor_id(), | 115 devinfo.vendor_id(), |
115 devinfo.product_id()), | 116 devinfo.product_id()), |
116 dispatcher_(dispatcher) { | 117 dispatcher_(dispatcher), |
118 palm_filter_(nullptr) { | |
117 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 119 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
118 switches::kExtraTouchNoiseFiltering)) { | 120 switches::kExtraTouchNoiseFiltering)) { |
119 touch_noise_finder_.reset(new TouchNoiseFinder); | 121 touch_noise_finder_.reset(new TouchNoiseFinder); |
120 } | 122 } |
121 touch_evdev_debug_buffer_.Initialize(devinfo); | 123 touch_evdev_debug_buffer_.Initialize(devinfo); |
122 } | 124 } |
123 | 125 |
124 TouchEventConverterEvdev::~TouchEventConverterEvdev() { | 126 TouchEventConverterEvdev::~TouchEventConverterEvdev() { |
125 } | 127 } |
126 | 128 |
127 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { | 129 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
128 has_mt_ = info.HasMultitouch(); | 130 has_mt_ = info.HasMultitouch(); |
131 has_pen_ = info.HasKeyEvent(BTN_TOOL_PEN); | |
129 | 132 |
130 if (has_mt_) { | 133 if (has_mt_) { |
131 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); | 134 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); |
132 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); | 135 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); |
133 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); | 136 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); |
134 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; | 137 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; |
135 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); | 138 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); |
136 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; | 139 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; |
137 touch_points_ = | 140 touch_points_ = |
138 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); | 141 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 events_[0].x = 0; | 201 events_[0].x = 0; |
199 events_[0].y = 0; | 202 events_[0].y = 0; |
200 events_[0].tracking_id = kTrackingIdForUnusedSlot; | 203 events_[0].tracking_id = kTrackingIdForUnusedSlot; |
201 events_[0].touching = false; | 204 events_[0].touching = false; |
202 events_[0].slot = 0; | 205 events_[0].slot = 0; |
203 events_[0].radius_x = 0; | 206 events_[0].radius_x = 0; |
204 events_[0].radius_y = 0; | 207 events_[0].radius_y = 0; |
205 events_[0].pressure = 0; | 208 events_[0].pressure = 0; |
206 events_[0].tool_code = 0; | 209 events_[0].tool_code = 0; |
207 } | 210 } |
211 | |
212 if (palm_filter_) | |
213 palm_filter_->Reset(); | |
208 } | 214 } |
209 | 215 |
210 void TouchEventConverterEvdev::Reinitialize() { | 216 void TouchEventConverterEvdev::Reinitialize() { |
211 ReleaseButtons(); | 217 ReleaseButtons(); |
212 | 218 |
213 EventDeviceInfo info; | 219 EventDeviceInfo info; |
214 if (!info.Initialize(fd_, path_)) { | 220 if (!info.Initialize(fd_, path_)) { |
215 LOG(ERROR) << "Failed to synchronize state for touch device: " | 221 LOG(ERROR) << "Failed to synchronize state for touch device: " |
216 << path_.value(); | 222 << path_.value(); |
217 Stop(); | 223 Stop(); |
218 return; | 224 return; |
219 } | 225 } |
220 Initialize(info); | 226 Initialize(info); |
221 } | 227 } |
222 | 228 |
223 bool TouchEventConverterEvdev::HasTouchscreen() const { | 229 bool TouchEventConverterEvdev::HasTouchscreen() const { |
224 return true; | 230 return true; |
225 } | 231 } |
226 | 232 |
233 bool TouchEventConverterEvdev::HasPen() const { | |
234 return has_pen_; | |
235 } | |
236 | |
227 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { | 237 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
228 return gfx::Size(x_num_tuxels_, y_num_tuxels_); | 238 return gfx::Size(x_num_tuxels_, y_num_tuxels_); |
229 } | 239 } |
230 | 240 |
231 int TouchEventConverterEvdev::GetTouchPoints() const { | 241 int TouchEventConverterEvdev::GetTouchPoints() const { |
232 return touch_points_; | 242 return touch_points_; |
233 } | 243 } |
234 | 244 |
235 void TouchEventConverterEvdev::OnEnabled() { | 245 void TouchEventConverterEvdev::OnEnabled() { |
236 ReportEvents(EventTimeForNow()); | 246 ReportEvents(EventTimeForNow()); |
237 } | 247 } |
238 | 248 |
239 void TouchEventConverterEvdev::OnDisabled() { | 249 void TouchEventConverterEvdev::OnDisabled() { |
240 ReleaseTouches(); | 250 ReleaseTouches(); |
241 ReleaseButtons(); | 251 ReleaseButtons(); |
252 if (palm_filter_) | |
253 palm_filter_->Reset(); | |
242 } | 254 } |
243 | 255 |
244 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 256 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
245 TRACE_EVENT1("evdev", | 257 TRACE_EVENT1("evdev", |
246 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", | 258 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", |
247 fd); | 259 fd); |
248 | 260 |
249 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; | 261 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; |
250 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 262 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
251 if (read_size < 0) { | 263 if (read_size < 0) { |
(...skipping 22 matching lines...) Expand all Loading... | |
274 } | 286 } |
275 | 287 |
276 void TouchEventConverterEvdev::DumpTouchEventLog(const char* filename) { | 288 void TouchEventConverterEvdev::DumpTouchEventLog(const char* filename) { |
277 touch_evdev_debug_buffer_.DumpLog(filename); | 289 touch_evdev_debug_buffer_.DumpLog(filename); |
278 } | 290 } |
279 | 291 |
280 void TouchEventConverterEvdev::SetTouchEventLoggingEnabled(bool enabled) { | 292 void TouchEventConverterEvdev::SetTouchEventLoggingEnabled(bool enabled) { |
281 touch_logging_enabled_ = enabled; | 293 touch_logging_enabled_ = enabled; |
282 } | 294 } |
283 | 295 |
296 void TouchEventConverterEvdev::SetPalmSuppressionFilter( | |
297 PalmSuppressionFilter* palm_filter) { | |
298 palm_filter_ = palm_filter; | |
299 } | |
300 | |
284 void TouchEventConverterEvdev::ProcessMultitouchEvent( | 301 void TouchEventConverterEvdev::ProcessMultitouchEvent( |
285 const input_event& input) { | 302 const input_event& input) { |
286 if (touch_logging_enabled_) | 303 if (touch_logging_enabled_) |
287 touch_evdev_debug_buffer_.ProcessEvent(current_slot_, &input); | 304 touch_evdev_debug_buffer_.ProcessEvent(current_slot_, &input); |
288 | 305 |
289 if (input.type == EV_SYN) { | 306 if (input.type == EV_SYN) { |
290 ProcessSyn(input); | 307 ProcessSyn(input); |
291 } else if (dropped_events_) { | 308 } else if (dropped_events_) { |
292 // Do nothing. This branch indicates we have lost sync with the driver. | 309 // Do nothing. This branch indicates we have lost sync with the driver. |
293 } else if (input.type == EV_ABS) { | 310 } else if (input.type == EV_ABS) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
345 // Do not change tool types while touching to prevent inconsistencies | 362 // Do not change tool types while touching to prevent inconsistencies |
346 // from switching between Mouse and TouchEvents. | 363 // from switching between Mouse and TouchEvents. |
347 if (events_[current_slot_].was_touching) | 364 if (events_[current_slot_].was_touching) |
348 break; | 365 break; |
349 | 366 |
350 if (input.value > 0) { | 367 if (input.value > 0) { |
351 events_[current_slot_].tool_code = input.code; | 368 events_[current_slot_].tool_code = input.code; |
352 } else { | 369 } else { |
353 events_[current_slot_].tool_code = 0; | 370 events_[current_slot_].tool_code = 0; |
354 } | 371 } |
372 events_[current_slot_].altered = true; | |
355 break; | 373 break; |
356 default: | 374 default: |
357 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 375 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
358 } | 376 } |
359 } | 377 } |
360 | 378 |
361 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { | 379 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
362 switch (input.code) { | 380 switch (input.code) { |
363 case ABS_MT_TOUCH_MAJOR: | 381 case ABS_MT_TOUCH_MAJOR: |
364 // TODO(spang): If we have all of major, minor, and orientation, | 382 // TODO(spang): If we have all of major, minor, and orientation, |
(...skipping 18 matching lines...) Expand all Loading... | |
383 break; | 401 break; |
384 case ABS_MT_SLOT: | 402 case ABS_MT_SLOT: |
385 if (input.value >= 0 && | 403 if (input.value >= 0 && |
386 static_cast<size_t>(input.value) < events_.size()) { | 404 static_cast<size_t>(input.value) < events_.size()) { |
387 current_slot_ = input.value; | 405 current_slot_ = input.value; |
388 } else { | 406 } else { |
389 LOG(ERROR) << "invalid touch event index: " << input.value; | 407 LOG(ERROR) << "invalid touch event index: " << input.value; |
390 return; | 408 return; |
391 } | 409 } |
392 break; | 410 break; |
411 case ABS_MT_TOOL_TYPE: | |
412 if (input.value == MT_TOOL_PALM) | |
413 events_[current_slot_].is_palm = true; | |
393 default: | 414 default: |
394 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; | 415 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; |
395 return; | 416 return; |
396 } | 417 } |
397 events_[current_slot_].altered = true; | 418 events_[current_slot_].altered = true; |
398 } | 419 } |
399 | 420 |
400 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { | 421 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { |
401 switch (input.code) { | 422 switch (input.code) { |
402 case SYN_REPORT: | 423 case SYN_REPORT: |
403 ReportEvents(EventConverterEvdev::TimeTicksFromInputEvent(input)); | 424 ReportEvents(EventConverterEvdev::TimeTicksFromInputEvent(input)); |
404 break; | 425 break; |
405 case SYN_DROPPED: | 426 case SYN_DROPPED: |
406 // Some buffer has overrun. We ignore all events up to and | 427 // Some buffer has overrun. We ignore all events up to and |
407 // including the next SYN_REPORT. | 428 // including the next SYN_REPORT. |
408 dropped_events_ = true; | 429 dropped_events_ = true; |
409 break; | 430 break; |
410 default: | 431 default: |
411 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; | 432 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; |
412 } | 433 } |
413 } | 434 } |
414 | 435 |
415 EventType TouchEventConverterEvdev::GetEventTypeForTouch( | 436 EventType TouchEventConverterEvdev::GetEventTypeForTouch( |
416 const InProgressTouchEvdev& touch) { | 437 const InProgressTouchEvdev& touch) { |
417 if (touch.cancelled) | 438 if (touch.cancelled) |
418 return ET_UNKNOWN; | 439 return ET_UNKNOWN; |
419 | 440 |
441 if (touch.is_palm) | |
442 return ET_TOUCH_CANCELLED; | |
443 | |
420 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { | 444 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { |
421 if (touch.touching && !touch.was_touching) | 445 if (touch.touching && !touch.was_touching) |
spang
2016/08/22 20:52:13
Do we need this same check so that a new slot does
denniskempin
2016/08/23 22:28:12
Done.
| |
422 return ET_UNKNOWN; | 446 return ET_UNKNOWN; |
423 return ET_TOUCH_CANCELLED; | 447 return ET_TOUCH_CANCELLED; |
424 } | 448 } |
425 | 449 |
426 if (touch.touching) | 450 if (touch.touching) |
427 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; | 451 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; |
428 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; | 452 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; |
429 } | 453 } |
430 | 454 |
431 void TouchEventConverterEvdev::ReportTouchEvent( | 455 void TouchEventConverterEvdev::ReportTouchEvent( |
432 const InProgressTouchEvdev& event, | 456 const InProgressTouchEvdev& event, |
433 EventType event_type, | 457 EventType event_type, |
434 base::TimeTicks timestamp) { | 458 base::TimeTicks timestamp) { |
435 dispatcher_->DispatchTouchEvent(TouchEventParams( | 459 TouchEventParams params(input_device_.id, event.slot, event_type, |
436 input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y), | 460 gfx::PointF(event.x, event.y), |
437 GetEventPointerDetails(event), timestamp)); | 461 GetEventPointerDetails(event), timestamp); |
462 if (!palm_filter_ || palm_filter_->FilterTouch(params)) | |
463 dispatcher_->DispatchTouchEvent(params); | |
438 } | 464 } |
439 | 465 |
440 void TouchEventConverterEvdev::ReportStylusEvent( | 466 void TouchEventConverterEvdev::ReportStylusEvent( |
441 const InProgressTouchEvdev& event, | 467 const InProgressTouchEvdev& event, |
442 base::TimeTicks timestamp) { | 468 base::TimeTicks timestamp) { |
443 if (event.btn_left.changed) | 469 if (event.btn_left.changed) |
444 ReportButton(BTN_LEFT, event.btn_left.down, event, timestamp); | 470 ReportButton(BTN_LEFT, event.btn_left.down, event, timestamp); |
445 if (event.btn_right.changed) | 471 if (event.btn_right.changed) |
446 ReportButton(BTN_RIGHT, event.btn_right.down, event, timestamp); | 472 ReportButton(BTN_RIGHT, event.btn_right.down, event, timestamp); |
447 if (event.btn_middle.changed) | 473 if (event.btn_middle.changed) |
(...skipping 20 matching lines...) Expand all Loading... | |
468 } | 494 } |
469 | 495 |
470 if (touch_noise_finder_) | 496 if (touch_noise_finder_) |
471 touch_noise_finder_->HandleTouches(events_, timestamp); | 497 touch_noise_finder_->HandleTouches(events_, timestamp); |
472 | 498 |
473 for (size_t i = 0; i < events_.size(); i++) { | 499 for (size_t i = 0; i < events_.size(); i++) { |
474 InProgressTouchEvdev* event = &events_[i]; | 500 InProgressTouchEvdev* event = &events_[i]; |
475 if (!event->altered) | 501 if (!event->altered) |
476 continue; | 502 continue; |
477 | 503 |
504 if (has_pen_ && palm_filter_) { | |
505 palm_filter_->EnableSuppression(event->tool_code > 0, timestamp); | |
506 } | |
507 | |
478 if (event->tool_code > 0) { | 508 if (event->tool_code > 0) { |
479 ReportStylusEvent(*event, timestamp); | 509 ReportStylusEvent(*event, timestamp); |
480 } else { | 510 } else { |
481 EventType event_type = GetEventTypeForTouch(*event); | 511 EventType event_type = GetEventTypeForTouch(*event); |
482 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) | 512 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) |
483 event->cancelled = true; | 513 event->cancelled = true; |
484 | 514 |
485 if (event_type != ET_UNKNOWN) | 515 if (event_type != ET_UNKNOWN) |
486 ReportTouchEvent(*event, event_type, timestamp); | 516 ReportTouchEvent(*event, event_type, timestamp); |
487 } | 517 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 if (pressure_max_ - pressure_min_) | 571 if (pressure_max_ - pressure_min_) |
542 pressure /= pressure_max_ - pressure_min_; | 572 pressure /= pressure_max_ - pressure_min_; |
543 return pressure; | 573 return pressure; |
544 } | 574 } |
545 | 575 |
546 int TouchEventConverterEvdev::NextTrackingId() { | 576 int TouchEventConverterEvdev::NextTrackingId() { |
547 return next_tracking_id_++ & kMaxTrackingId; | 577 return next_tracking_id_++ & kMaxTrackingId; |
548 } | 578 } |
549 | 579 |
550 } // namespace ui | 580 } // namespace ui |
OLD | NEW |