Chromium Code Reviews| 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 |