| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 return ABS_MT_POSITION_Y; | 71 return ABS_MT_POSITION_Y; |
| 72 case ABS_PRESSURE: | 72 case ABS_PRESSURE: |
| 73 return ABS_MT_PRESSURE; | 73 return ABS_MT_PRESSURE; |
| 74 case ABS_DISTANCE: | 74 case ABS_DISTANCE: |
| 75 return ABS_MT_DISTANCE; | 75 return ABS_MT_DISTANCE; |
| 76 default: | 76 default: |
| 77 return -1; | 77 return -1; |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 ui::EventPointerType GetPointerTypeFromEvent( | 81 ui::PointerDetails GetEventPointerDetails( |
| 82 const ui::InProgressTouchEvdev& event) { | 82 const ui::InProgressTouchEvdev& event) { |
| 83 return (event.tool_code == BTN_TOOL_PEN) | 83 ui::EventPointerType type; |
| 84 ? ui::EventPointerType::POINTER_TYPE_PEN | 84 switch (event.tool_code) { |
| 85 : ui::EventPointerType::POINTER_TYPE_TOUCH; | 85 case BTN_TOOL_PEN: |
| 86 type = ui::EventPointerType::POINTER_TYPE_PEN; |
| 87 break; |
| 88 default: |
| 89 type = ui::EventPointerType::POINTER_TYPE_TOUCH; |
| 90 } |
| 91 return ui::PointerDetails(type, event.radius_x, event.radius_y, |
| 92 event.pressure, |
| 93 /* tilt_x */ 0.0f, |
| 94 /* tilt_y */ 0.0f); |
| 86 } | 95 } |
| 87 | 96 |
| 88 const int kTrackingIdForUnusedSlot = -1; | 97 const int kTrackingIdForUnusedSlot = -1; |
| 89 | 98 |
| 90 } // namespace | 99 } // namespace |
| 91 | 100 |
| 92 namespace ui { | 101 namespace ui { |
| 93 | 102 |
| 94 TouchEventConverterEvdev::TouchEventConverterEvdev( | 103 TouchEventConverterEvdev::TouchEventConverterEvdev( |
| 95 int fd, | 104 int fd, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; | 159 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; |
| 151 y_min_tuxels_ += cal.bezel_top; | 160 y_min_tuxels_ += cal.bezel_top; |
| 152 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; | 161 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; |
| 153 | 162 |
| 154 VLOG(1) << "applying touch calibration: " | 163 VLOG(1) << "applying touch calibration: " |
| 155 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, | 164 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, |
| 156 cal.bezel_right, cal.bezel_top, | 165 cal.bezel_right, cal.bezel_top, |
| 157 cal.bezel_bottom); | 166 cal.bezel_bottom); |
| 158 } | 167 } |
| 159 | 168 |
| 169 // TODO(denniskempin): Use EVIOCGKEY to synchronize key state. |
| 170 |
| 160 events_.resize(touch_points_); | 171 events_.resize(touch_points_); |
| 161 | 172 |
| 162 if (has_mt_) { | 173 if (has_mt_) { |
| 163 for (size_t i = 0; i < events_.size(); ++i) { | 174 for (size_t i = 0; i < events_.size(); ++i) { |
| 164 events_[i].x = info.GetAbsMtSlotValueWithDefault(ABS_MT_POSITION_X, i, 0); | 175 events_[i].x = info.GetAbsMtSlotValueWithDefault(ABS_MT_POSITION_X, i, 0); |
| 165 events_[i].y = info.GetAbsMtSlotValueWithDefault(ABS_MT_POSITION_Y, i, 0); | 176 events_[i].y = info.GetAbsMtSlotValueWithDefault(ABS_MT_POSITION_Y, i, 0); |
| 166 events_[i].tracking_id = info.GetAbsMtSlotValueWithDefault( | 177 events_[i].tracking_id = info.GetAbsMtSlotValueWithDefault( |
| 167 ABS_MT_TRACKING_ID, i, kTrackingIdForUnusedSlot); | 178 ABS_MT_TRACKING_ID, i, kTrackingIdForUnusedSlot); |
| 168 events_[i].touching = (events_[i].tracking_id >= 0); | 179 events_[i].touching = (events_[i].tracking_id >= 0); |
| 169 events_[i].slot = i; | 180 events_[i].slot = i; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 190 events_[0].touching = false; | 201 events_[0].touching = false; |
| 191 events_[0].slot = 0; | 202 events_[0].slot = 0; |
| 192 events_[0].radius_x = 0; | 203 events_[0].radius_x = 0; |
| 193 events_[0].radius_y = 0; | 204 events_[0].radius_y = 0; |
| 194 events_[0].pressure = 0; | 205 events_[0].pressure = 0; |
| 195 events_[0].tool_code = 0; | 206 events_[0].tool_code = 0; |
| 196 } | 207 } |
| 197 } | 208 } |
| 198 | 209 |
| 199 void TouchEventConverterEvdev::Reinitialize() { | 210 void TouchEventConverterEvdev::Reinitialize() { |
| 211 ReleaseButtons(); |
| 212 |
| 200 EventDeviceInfo info; | 213 EventDeviceInfo info; |
| 201 if (!info.Initialize(fd_, path_)) { | 214 if (!info.Initialize(fd_, path_)) { |
| 202 LOG(ERROR) << "Failed to synchronize state for touch device: " | 215 LOG(ERROR) << "Failed to synchronize state for touch device: " |
| 203 << path_.value(); | 216 << path_.value(); |
| 204 Stop(); | 217 Stop(); |
| 205 return; | 218 return; |
| 206 } | 219 } |
| 207 | |
| 208 Initialize(info); | 220 Initialize(info); |
| 209 } | 221 } |
| 210 | 222 |
| 211 bool TouchEventConverterEvdev::HasTouchscreen() const { | 223 bool TouchEventConverterEvdev::HasTouchscreen() const { |
| 212 return true; | 224 return true; |
| 213 } | 225 } |
| 214 | 226 |
| 215 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { | 227 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
| 216 return gfx::Size(x_num_tuxels_, y_num_tuxels_); | 228 return gfx::Size(x_num_tuxels_, y_num_tuxels_); |
| 217 } | 229 } |
| 218 | 230 |
| 219 int TouchEventConverterEvdev::GetTouchPoints() const { | 231 int TouchEventConverterEvdev::GetTouchPoints() const { |
| 220 return touch_points_; | 232 return touch_points_; |
| 221 } | 233 } |
| 222 | 234 |
| 223 void TouchEventConverterEvdev::OnEnabled() { | 235 void TouchEventConverterEvdev::OnEnabled() { |
| 224 ReportEvents(EventTimeForNow()); | 236 ReportEvents(EventTimeForNow()); |
| 225 } | 237 } |
| 226 | 238 |
| 227 void TouchEventConverterEvdev::OnDisabled() { | 239 void TouchEventConverterEvdev::OnDisabled() { |
| 228 ReleaseTouches(); | 240 ReleaseTouches(); |
| 241 ReleaseButtons(); |
| 229 } | 242 } |
| 230 | 243 |
| 231 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 244 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
| 232 TRACE_EVENT1("evdev", | 245 TRACE_EVENT1("evdev", |
| 233 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", | 246 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", |
| 234 fd); | 247 fd); |
| 235 | 248 |
| 236 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; | 249 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; |
| 237 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 250 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
| 238 if (read_size < 0) { | 251 if (read_size < 0) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 event.value ? NextTrackingId() : kTrackingIdForUnusedSlot; | 323 event.value ? NextTrackingId() : kTrackingIdForUnusedSlot; |
| 311 ProcessMultitouchEvent(emulated_event); | 324 ProcessMultitouchEvent(emulated_event); |
| 312 } | 325 } |
| 313 } | 326 } |
| 314 } | 327 } |
| 315 | 328 |
| 316 void TouchEventConverterEvdev::ProcessKey(const input_event& input) { | 329 void TouchEventConverterEvdev::ProcessKey(const input_event& input) { |
| 317 switch (input.code) { | 330 switch (input.code) { |
| 318 case BTN_TOUCH: | 331 case BTN_TOUCH: |
| 319 case BTN_LEFT: | 332 case BTN_LEFT: |
| 333 events_[current_slot_].btn_left.down = input.value; |
| 334 events_[current_slot_].btn_left.changed = true; |
| 335 break; |
| 336 case BTN_STYLUS: |
| 337 events_[current_slot_].btn_right.down = input.value; |
| 338 events_[current_slot_].btn_right.changed = true; |
| 339 break; |
| 340 case BTN_STYLUS2: |
| 341 events_[current_slot_].btn_middle.down = input.value; |
| 342 events_[current_slot_].btn_middle.changed = true; |
| 320 break; | 343 break; |
| 321 case BTN_TOOL_PEN: | 344 case BTN_TOOL_PEN: |
| 345 // Do not change tool types while touching to prevent inconsistencies |
| 346 // from switching between Mouse and TouchEvents. |
| 347 if (events_[current_slot_].was_touching) |
| 348 break; |
| 349 |
| 322 if (input.value > 0) { | 350 if (input.value > 0) { |
| 323 events_[current_slot_].tool_code = input.code; | 351 events_[current_slot_].tool_code = input.code; |
| 324 } else { | 352 } else { |
| 325 events_[current_slot_].tool_code = 0; | 353 events_[current_slot_].tool_code = 0; |
| 326 } | 354 } |
| 327 break; | 355 break; |
| 328 default: | 356 default: |
| 329 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 357 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
| 330 } | 358 } |
| 331 } | 359 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 if (touch.touching && !touch.was_touching) | 421 if (touch.touching && !touch.was_touching) |
| 394 return ET_UNKNOWN; | 422 return ET_UNKNOWN; |
| 395 return ET_TOUCH_CANCELLED; | 423 return ET_TOUCH_CANCELLED; |
| 396 } | 424 } |
| 397 | 425 |
| 398 if (touch.touching) | 426 if (touch.touching) |
| 399 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; | 427 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; |
| 400 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; | 428 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; |
| 401 } | 429 } |
| 402 | 430 |
| 403 void TouchEventConverterEvdev::ReportEvent(const InProgressTouchEvdev& event, | 431 void TouchEventConverterEvdev::ReportTouchEvent( |
| 404 EventType event_type, | 432 const InProgressTouchEvdev& event, |
| 405 base::TimeTicks timestamp) { | 433 EventType event_type, |
| 406 PointerDetails details(GetPointerTypeFromEvent(event), event.radius_x, | 434 base::TimeTicks timestamp) { |
| 407 event.radius_y, event.pressure, | 435 dispatcher_->DispatchTouchEvent(TouchEventParams( |
| 408 /* tilt_x */ 0.0f, | 436 input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y), |
| 409 /* tilt_y */ 0.0f); | 437 GetEventPointerDetails(event), timestamp)); |
| 410 dispatcher_->DispatchTouchEvent( | 438 } |
| 411 TouchEventParams(input_device_.id, event.slot, event_type, | 439 |
| 412 gfx::PointF(event.x, event.y), details, timestamp)); | 440 void TouchEventConverterEvdev::ReportStylusEvent( |
| 441 const InProgressTouchEvdev& event, |
| 442 base::TimeTicks timestamp) { |
| 443 if (event.btn_left.changed) |
| 444 ReportButton(BTN_LEFT, event.btn_left.down, event, timestamp); |
| 445 if (event.btn_right.changed) |
| 446 ReportButton(BTN_RIGHT, event.btn_right.down, event, timestamp); |
| 447 if (event.btn_middle.changed) |
| 448 ReportButton(BTN_MIDDLE, event.btn_middle.down, event, timestamp); |
| 449 |
| 450 dispatcher_->DispatchMouseMoveEvent(MouseMoveEventParams( |
| 451 input_device_.id, EF_DIRECT_INPUT, gfx::PointF(event.x, event.y), |
| 452 GetEventPointerDetails(event), timestamp)); |
| 453 } |
| 454 |
| 455 void TouchEventConverterEvdev::ReportButton(unsigned int button, |
| 456 bool down, |
| 457 const InProgressTouchEvdev& event, |
| 458 base::TimeTicks timestamp) { |
| 459 dispatcher_->DispatchMouseButtonEvent(MouseButtonEventParams( |
| 460 input_device_.id, EF_DIRECT_INPUT, gfx::PointF(event.x, event.y), button, |
| 461 down, false /* allow_remap */, GetEventPointerDetails(event), timestamp)); |
| 413 } | 462 } |
| 414 | 463 |
| 415 void TouchEventConverterEvdev::ReportEvents(base::TimeTicks timestamp) { | 464 void TouchEventConverterEvdev::ReportEvents(base::TimeTicks timestamp) { |
| 416 if (dropped_events_) { | 465 if (dropped_events_) { |
| 417 Reinitialize(); | 466 Reinitialize(); |
| 418 dropped_events_ = false; | 467 dropped_events_ = false; |
| 419 } | 468 } |
| 420 | 469 |
| 421 if (touch_noise_finder_) | 470 if (touch_noise_finder_) |
| 422 touch_noise_finder_->HandleTouches(events_, timestamp); | 471 touch_noise_finder_->HandleTouches(events_, timestamp); |
| 423 | 472 |
| 424 for (size_t i = 0; i < events_.size(); i++) { | 473 for (size_t i = 0; i < events_.size(); i++) { |
| 425 InProgressTouchEvdev* event = &events_[i]; | 474 InProgressTouchEvdev* event = &events_[i]; |
| 426 if (!event->altered) | 475 if (!event->altered) |
| 427 continue; | 476 continue; |
| 428 | 477 |
| 429 EventType event_type = GetEventTypeForTouch(*event); | 478 if (event->tool_code > 0) { |
| 430 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) | 479 ReportStylusEvent(*event, timestamp); |
| 431 event->cancelled = true; | 480 } else { |
| 481 EventType event_type = GetEventTypeForTouch(*event); |
| 482 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) |
| 483 event->cancelled = true; |
| 432 | 484 |
| 433 if (event_type != ET_UNKNOWN) | 485 if (event_type != ET_UNKNOWN) |
| 434 ReportEvent(*event, event_type, timestamp); | 486 ReportTouchEvent(*event, event_type, timestamp); |
| 487 } |
| 435 | 488 |
| 436 event->was_touching = event->touching; | 489 event->was_touching = event->touching; |
| 437 event->altered = false; | 490 event->altered = false; |
| 491 event->btn_left.changed = false; |
| 492 event->btn_right.changed = false; |
| 493 event->btn_middle.changed = false; |
| 438 } | 494 } |
| 439 } | 495 } |
| 440 | 496 |
| 441 void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) { | 497 void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) { |
| 442 InProgressTouchEvdev* event = &events_[slot]; | 498 InProgressTouchEvdev* event = &events_[slot]; |
| 443 | 499 |
| 444 if (event->tracking_id == tracking_id) | 500 if (event->tracking_id == tracking_id) |
| 445 return; | 501 return; |
| 446 | 502 |
| 447 event->tracking_id = tracking_id; | 503 event->tracking_id = tracking_id; |
| 448 event->touching = (tracking_id >= 0); | 504 event->touching = (tracking_id >= 0); |
| 449 event->altered = true; | 505 event->altered = true; |
| 450 | 506 |
| 451 if (tracking_id >= 0) | 507 if (tracking_id >= 0) |
| 452 event->cancelled = false; | 508 event->cancelled = false; |
| 453 } | 509 } |
| 454 | 510 |
| 455 void TouchEventConverterEvdev::ReleaseTouches() { | 511 void TouchEventConverterEvdev::ReleaseTouches() { |
| 456 for (size_t slot = 0; slot < events_.size(); slot++) | 512 for (size_t slot = 0; slot < events_.size(); slot++) |
| 457 UpdateTrackingId(slot, kTrackingIdForUnusedSlot); | 513 UpdateTrackingId(slot, kTrackingIdForUnusedSlot); |
| 458 | 514 |
| 459 ReportEvents(EventTimeForNow()); | 515 ReportEvents(EventTimeForNow()); |
| 460 } | 516 } |
| 461 | 517 |
| 518 void TouchEventConverterEvdev::ReleaseButtons() { |
| 519 for (size_t slot = 0; slot < events_.size(); slot++) { |
| 520 InProgressTouchEvdev* event = &events_[slot]; |
| 521 |
| 522 if (event->btn_left.down) { |
| 523 event->btn_left.down = false; |
| 524 event->btn_left.changed = true; |
| 525 } |
| 526 if (event->btn_right.down) { |
| 527 event->btn_right.down = false; |
| 528 event->btn_right.changed = true; |
| 529 } |
| 530 if (event->btn_middle.down) { |
| 531 event->btn_middle.down = false; |
| 532 event->btn_middle.changed = true; |
| 533 } |
| 534 } |
| 535 |
| 536 ReportEvents(EventTimeForNow()); |
| 537 } |
| 538 |
| 462 float TouchEventConverterEvdev::ScalePressure(int32_t value) { | 539 float TouchEventConverterEvdev::ScalePressure(int32_t value) { |
| 463 float pressure = value - pressure_min_; | 540 float pressure = value - pressure_min_; |
| 464 if (pressure_max_ - pressure_min_) | 541 if (pressure_max_ - pressure_min_) |
| 465 pressure /= pressure_max_ - pressure_min_; | 542 pressure /= pressure_max_ - pressure_min_; |
| 466 return pressure; | 543 return pressure; |
| 467 } | 544 } |
| 468 | 545 |
| 469 int TouchEventConverterEvdev::NextTrackingId() { | 546 int TouchEventConverterEvdev::NextTrackingId() { |
| 470 return next_tracking_id_++ & kMaxTrackingId; | 547 return next_tracking_id_++ & kMaxTrackingId; |
| 471 } | 548 } |
| 472 | 549 |
| 473 } // namespace ui | 550 } // namespace ui |
| OLD | NEW |