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/chromeos/touch_exploration_controller.h" | 5 #include "ui/chromeos/touch_exploration_controller.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 const int kSoundDelayInMS = 150; | 30 const int kSoundDelayInMS = 150; |
31 | 31 |
32 } // namespace | 32 } // namespace |
33 | 33 |
34 TouchExplorationController::TouchExplorationController( | 34 TouchExplorationController::TouchExplorationController( |
35 aura::Window* root_window, | 35 aura::Window* root_window, |
36 TouchExplorationControllerDelegate* delegate) | 36 TouchExplorationControllerDelegate* delegate) |
37 : root_window_(root_window), | 37 : root_window_(root_window), |
38 delegate_(delegate), | 38 delegate_(delegate), |
39 state_(NO_FINGERS_DOWN), | 39 state_(NO_FINGERS_DOWN), |
| 40 anchor_point_state_(ANCHOR_POINT_NONE), |
40 gesture_provider_(new GestureProviderAura(this, this)), | 41 gesture_provider_(new GestureProviderAura(this, this)), |
41 prev_state_(NO_FINGERS_DOWN), | 42 prev_state_(NO_FINGERS_DOWN), |
42 VLOG_on_(true), | 43 VLOG_on_(true), |
43 tick_clock_(NULL) { | 44 tick_clock_(NULL) { |
44 DCHECK(root_window); | 45 DCHECK(root_window); |
45 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); | 46 root_window->GetHost()->GetEventSource()->AddEventRewriter(this); |
46 } | 47 } |
47 | 48 |
48 TouchExplorationController::~TouchExplorationController() { | 49 TouchExplorationController::~TouchExplorationController() { |
49 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); | 50 root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
50 } | 51 } |
51 | 52 |
| 53 void TouchExplorationController::SetTouchAccessibilityAnchorPoint( |
| 54 const gfx::Point& anchor_point) { |
| 55 gfx::Point native_point = anchor_point; |
| 56 root_window_->GetHost()->ConvertPointToNativeScreen(&native_point); |
| 57 |
| 58 anchor_point_ = gfx::PointF(native_point.x(), native_point.y()); |
| 59 anchor_point_state_ = ANCHOR_POINT_EXPLICITLY_SET; |
| 60 } |
| 61 |
52 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 62 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
53 const ui::Event& event, | 63 const ui::Event& event, |
54 std::unique_ptr<ui::Event>* rewritten_event) { | 64 std::unique_ptr<ui::Event>* rewritten_event) { |
55 if (!event.IsTouchEvent()) { | 65 if (!event.IsTouchEvent()) { |
56 if (event.IsKeyEvent()) { | 66 if (event.IsKeyEvent()) { |
57 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); | 67 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); |
58 VLOG(0) << "\nKeyboard event: " << key_event.name() | 68 VLOG(0) << "\nKeyboard event: " << key_event.name() |
59 << "\n Key code: " << key_event.key_code() | 69 << "\n Key code: " << key_event.key_code() |
60 << ", Flags: " << key_event.flags() | 70 << ", Flags: " << key_event.flags() |
61 << ", Is char: " << key_event.is_char(); | 71 << ", Is char: " << key_event.is_char(); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 SET_STATE(SLIDE_GESTURE); | 298 SET_STATE(SLIDE_GESTURE); |
289 return InSlideGesture(event, rewritten_event); | 299 return InSlideGesture(event, rewritten_event); |
290 } | 300 } |
291 | 301 |
292 // If the user moves fast enough from the initial touch location, start | 302 // If the user moves fast enough from the initial touch location, start |
293 // gesture detection. Otherwise, jump to the touch exploration mode early. | 303 // gesture detection. Otherwise, jump to the touch exploration mode early. |
294 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { | 304 if (velocity > gesture_detector_config_.minimum_swipe_velocity) { |
295 SET_STATE(GESTURE_IN_PROGRESS); | 305 SET_STATE(GESTURE_IN_PROGRESS); |
296 return InGestureInProgress(event, rewritten_event); | 306 return InGestureInProgress(event, rewritten_event); |
297 } | 307 } |
| 308 anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
298 EnterTouchToMouseMode(); | 309 EnterTouchToMouseMode(); |
299 SET_STATE(TOUCH_EXPLORATION); | 310 SET_STATE(TOUCH_EXPLORATION); |
300 return InTouchExploration(event, rewritten_event); | 311 return InTouchExploration(event, rewritten_event); |
301 } | 312 } |
302 NOTREACHED(); | 313 NOTREACHED(); |
303 return ui::EVENT_REWRITE_CONTINUE; | 314 return ui::EVENT_REWRITE_CONTINUE; |
304 } | 315 } |
305 | 316 |
306 ui::EventRewriteStatus | 317 ui::EventRewriteStatus |
307 TouchExplorationController::InSingleTapOrTouchExploreReleased( | 318 TouchExplorationController::InSingleTapOrTouchExploreReleased( |
308 const ui::TouchEvent& event, | 319 const ui::TouchEvent& event, |
309 std::unique_ptr<ui::Event>* rewritten_event) { | 320 std::unique_ptr<ui::Event>* rewritten_event) { |
310 const ui::EventType type = event.type(); | 321 const ui::EventType type = event.type(); |
311 // If there is more than one finger down, then discard to wait until no | 322 // If there is more than one finger down, then discard to wait until no |
312 // fingers are down. | 323 // fingers are down. |
313 if (current_touch_ids_.size() > 1) { | 324 if (current_touch_ids_.size() > 1) { |
314 SET_STATE(WAIT_FOR_NO_FINGERS); | 325 SET_STATE(WAIT_FOR_NO_FINGERS); |
315 return ui::EVENT_REWRITE_DISCARD; | 326 return ui::EVENT_REWRITE_DISCARD; |
316 } | 327 } |
317 if (type == ui::ET_TOUCH_PRESSED) { | 328 if (type == ui::ET_TOUCH_PRESSED) { |
318 // If there is no touch exploration yet, we can't send a click, so discard. | 329 // If there is no anchor point for synthesized events because the |
319 if (!last_touch_exploration_) { | 330 // user hasn't touch-explored or focused anything yet, we can't |
| 331 // send a click, so discard. |
| 332 if (anchor_point_state_ == ANCHOR_POINT_NONE) { |
320 tap_timer_.Stop(); | 333 tap_timer_.Stop(); |
321 return ui::EVENT_REWRITE_DISCARD; | 334 return ui::EVENT_REWRITE_DISCARD; |
322 } | 335 } |
323 // This is the second tap in a double-tap (or double tap-hold). | 336 // This is the second tap in a double-tap (or double tap-hold). |
324 // We set the tap timer. If it fires before the user lifts their finger, | 337 // We set the tap timer. If it fires before the user lifts their finger, |
325 // one-finger passthrough begins. Otherwise, there is a touch press and | 338 // one-finger passthrough begins. Otherwise, there is a touch press and |
326 // release at the location of the last touch exploration. | 339 // release at the location of the last touch exploration. |
327 SET_STATE(DOUBLE_TAP_PENDING); | 340 SET_STATE(DOUBLE_TAP_PENDING); |
328 // The old tap timer (from the initial click) is stopped if it is still | 341 // The old tap timer (from the initial click) is stopped if it is still |
329 // going, and the new one is set. | 342 // going, and the new one is set. |
330 tap_timer_.Stop(); | 343 tap_timer_.Stop(); |
331 StartTapTimer(); | 344 StartTapTimer(); |
332 // This will update as the finger moves before a possible passthrough, and | 345 // This will update as the finger moves before a possible passthrough, and |
333 // will determine the offset. | 346 // will determine the offset. |
334 last_unused_finger_event_.reset(new ui::TouchEvent(event)); | 347 last_unused_finger_event_.reset(new ui::TouchEvent(event)); |
335 return ui::EVENT_REWRITE_DISCARD; | 348 return ui::EVENT_REWRITE_DISCARD; |
336 } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { | 349 } else if (type == ui::ET_TOUCH_RELEASED && |
| 350 anchor_point_state_ == ANCHOR_POINT_NONE) { |
337 // If the previous press was discarded, we need to also handle its | 351 // If the previous press was discarded, we need to also handle its |
338 // release. | 352 // release. |
339 if (current_touch_ids_.size() == 0) { | 353 if (current_touch_ids_.size() == 0) { |
340 SET_STATE(NO_FINGERS_DOWN); | 354 SET_STATE(NO_FINGERS_DOWN); |
341 } | 355 } |
342 return ui::EVENT_REWRITE_DISCARD; | 356 return ui::EVENT_REWRITE_DISCARD; |
343 } else if (type == ui::ET_TOUCH_MOVED) { | 357 } else if (type == ui::ET_TOUCH_MOVED) { |
344 return ui::EVENT_REWRITE_DISCARD; | 358 return ui::EVENT_REWRITE_DISCARD; |
345 } | 359 } |
346 NOTREACHED(); | 360 NOTREACHED(); |
(...skipping 12 matching lines...) Expand all Loading... |
359 float delta = (event.location() - initial_press_->location()).Length(); | 373 float delta = (event.location() - initial_press_->location()).Length(); |
360 if (delta > gesture_detector_config_.touch_slop) { | 374 if (delta > gesture_detector_config_.touch_slop) { |
361 tap_timer_.Stop(); | 375 tap_timer_.Stop(); |
362 OnTapTimerFired(); | 376 OnTapTimerFired(); |
363 } | 377 } |
364 return EVENT_REWRITE_DISCARD; | 378 return EVENT_REWRITE_DISCARD; |
365 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 379 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
366 if (current_touch_ids_.size() != 0) | 380 if (current_touch_ids_.size() != 0) |
367 return EVENT_REWRITE_DISCARD; | 381 return EVENT_REWRITE_DISCARD; |
368 | 382 |
369 std::unique_ptr<ui::TouchEvent> touch_press; | 383 SendSimulatedClick(); |
370 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), | |
371 initial_press_->touch_id(), | |
372 event.time_stamp())); | |
373 touch_press->set_location_f(last_touch_exploration_->location_f()); | |
374 touch_press->set_root_location_f(last_touch_exploration_->location_f()); | |
375 DispatchEvent(touch_press.get()); | |
376 | 384 |
377 std::unique_ptr<ui::TouchEvent> new_event( | |
378 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), | |
379 initial_press_->touch_id(), event.time_stamp())); | |
380 new_event->set_location_f(last_touch_exploration_->location_f()); | |
381 new_event->set_root_location_f(last_touch_exploration_->location_f()); | |
382 new_event->set_flags(event.flags()); | |
383 *rewritten_event = std::move(new_event); | |
384 SET_STATE(NO_FINGERS_DOWN); | 385 SET_STATE(NO_FINGERS_DOWN); |
385 return ui::EVENT_REWRITE_REWRITTEN; | 386 return ui::EVENT_REWRITE_DISCARD; |
386 } | 387 } |
387 NOTREACHED(); | 388 NOTREACHED(); |
388 return ui::EVENT_REWRITE_CONTINUE; | 389 return ui::EVENT_REWRITE_CONTINUE; |
389 } | 390 } |
390 | 391 |
391 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( | 392 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( |
392 const ui::TouchEvent& event, | 393 const ui::TouchEvent& event, |
393 std::unique_ptr<ui::Event>* rewritten_event) { | 394 std::unique_ptr<ui::Event>* rewritten_event) { |
394 const ui::EventType type = event.type(); | 395 const ui::EventType type = event.type(); |
395 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { | 396 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { |
396 return ui::EVENT_REWRITE_DISCARD; | 397 return ui::EVENT_REWRITE_DISCARD; |
397 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 398 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
398 if (current_touch_ids_.size() != 0) | 399 if (current_touch_ids_.size() != 0) |
399 return EVENT_REWRITE_DISCARD; | 400 return EVENT_REWRITE_DISCARD; |
400 | 401 |
401 std::unique_ptr<ui::TouchEvent> new_event( | 402 SendSimulatedClick(); |
402 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), | |
403 initial_press_->touch_id(), event.time_stamp())); | |
404 new_event->set_location_f(last_touch_exploration_->location_f()); | |
405 new_event->set_root_location_f(last_touch_exploration_->location_f()); | |
406 new_event->set_flags(event.flags()); | |
407 *rewritten_event = std::move(new_event); | |
408 SET_STATE(NO_FINGERS_DOWN); | 403 SET_STATE(NO_FINGERS_DOWN); |
409 return ui::EVENT_REWRITE_REWRITTEN; | 404 return ui::EVENT_REWRITE_DISCARD; |
410 } | 405 } |
411 NOTREACHED(); | 406 NOTREACHED(); |
412 return ui::EVENT_REWRITE_CONTINUE; | 407 return ui::EVENT_REWRITE_CONTINUE; |
413 } | 408 } |
414 | 409 |
415 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( | 410 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( |
416 const ui::TouchEvent& event, | 411 const ui::TouchEvent& event, |
417 std::unique_ptr<ui::Event>* rewritten_event) { | 412 std::unique_ptr<ui::Event>* rewritten_event) { |
418 const ui::EventType type = event.type(); | 413 const ui::EventType type = event.type(); |
419 if (type == ui::ET_TOUCH_PRESSED) { | 414 if (type == ui::ET_TOUCH_PRESSED) { |
420 // Handle split-tap. | 415 // Enter split-tap mode. |
421 initial_press_.reset(new TouchEvent(event)); | 416 initial_press_.reset(new TouchEvent(event)); |
422 tap_timer_.Stop(); | 417 tap_timer_.Stop(); |
423 std::unique_ptr<ui::TouchEvent> new_event( | |
424 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), event.touch_id(), | |
425 event.time_stamp())); | |
426 new_event->set_location_f(last_touch_exploration_->location_f()); | |
427 new_event->set_root_location_f(last_touch_exploration_->location_f()); | |
428 new_event->set_flags(event.flags()); | |
429 *rewritten_event = std::move(new_event); | |
430 SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); | 418 SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); |
431 return ui::EVENT_REWRITE_REWRITTEN; | 419 return ui::EVENT_REWRITE_DISCARD; |
432 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 420 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
433 initial_press_.reset(new TouchEvent(event)); | 421 initial_press_.reset(new TouchEvent(event)); |
434 StartTapTimer(); | 422 StartTapTimer(); |
435 SET_STATE(TOUCH_EXPLORE_RELEASED); | 423 SET_STATE(TOUCH_EXPLORE_RELEASED); |
436 } else if (type != ui::ET_TOUCH_MOVED) { | 424 } else if (type != ui::ET_TOUCH_MOVED) { |
437 NOTREACHED(); | 425 NOTREACHED(); |
438 return ui::EVENT_REWRITE_CONTINUE; | 426 return ui::EVENT_REWRITE_CONTINUE; |
439 } | 427 } |
440 | 428 |
441 // Rewrite as a mouse-move event. | 429 // Rewrite as a mouse-move event. |
442 *rewritten_event = CreateMouseMoveEvent(event.location_f(), event.flags()); | 430 *rewritten_event = CreateMouseMoveEvent(event.location_f(), event.flags()); |
443 last_touch_exploration_.reset(new TouchEvent(event)); | 431 last_touch_exploration_.reset(new TouchEvent(event)); |
| 432 if (anchor_point_state_ != ANCHOR_POINT_EXPLICITLY_SET) |
| 433 anchor_point_ = last_touch_exploration_->location_f(); |
| 434 |
444 return ui::EVENT_REWRITE_REWRITTEN; | 435 return ui::EVENT_REWRITE_REWRITTEN; |
445 } | 436 } |
446 | 437 |
447 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress( | 438 ui::EventRewriteStatus TouchExplorationController::InGestureInProgress( |
448 const ui::TouchEvent& event, | 439 const ui::TouchEvent& event, |
449 std::unique_ptr<ui::Event>* rewritten_event) { | 440 std::unique_ptr<ui::Event>* rewritten_event) { |
450 // The events were sent to the gesture provider in RewriteEvent already. | 441 // The events were sent to the gesture provider in RewriteEvent already. |
451 // If no gesture is registered before the tap timer times out, the state | 442 // If no gesture is registered before the tap timer times out, the state |
452 // will change to "wait for no fingers down" or "touch exploration" depending | 443 // will change to "wait for no fingers down" or "touch exploration" depending |
453 // on the number of fingers down, and this function will stop being called. | 444 // on the number of fingers down, and this function will stop being called. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 ui::EventType type = event.type(); | 509 ui::EventType type = event.type(); |
519 gfx::PointF location = event.location_f(); | 510 gfx::PointF location = event.location_f(); |
520 if (type == ui::ET_TOUCH_PRESSED) { | 511 if (type == ui::ET_TOUCH_PRESSED) { |
521 // A third finger being pressed means that a split tap can no longer go | 512 // A third finger being pressed means that a split tap can no longer go |
522 // through. The user enters the wait state, Since there has already been | 513 // through. The user enters the wait state, Since there has already been |
523 // a press dispatched when split tap began, the touch needs to be | 514 // a press dispatched when split tap began, the touch needs to be |
524 // cancelled. | 515 // cancelled. |
525 std::unique_ptr<ui::TouchEvent> new_event( | 516 std::unique_ptr<ui::TouchEvent> new_event( |
526 new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, gfx::Point(), | 517 new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, gfx::Point(), |
527 initial_press_->touch_id(), event.time_stamp())); | 518 initial_press_->touch_id(), event.time_stamp())); |
528 new_event->set_location_f(last_touch_exploration_->location_f()); | 519 // TODO(dmazzoni): fix for multiple displays. http://crbug.com/616793 |
529 new_event->set_root_location_f(last_touch_exploration_->location_f()); | 520 new_event->set_location_f(anchor_point_); |
| 521 new_event->set_root_location_f(anchor_point_); |
530 new_event->set_flags(event.flags()); | 522 new_event->set_flags(event.flags()); |
531 *rewritten_event = std::move(new_event); | 523 *rewritten_event = std::move(new_event); |
532 SET_STATE(WAIT_FOR_NO_FINGERS); | 524 SET_STATE(WAIT_FOR_NO_FINGERS); |
533 return ui::EVENT_REWRITE_REWRITTEN; | 525 return ui::EVENT_REWRITE_REWRITTEN; |
534 } else if (type == ui::ET_TOUCH_MOVED) { | 526 } else if (type == ui::ET_TOUCH_MOVED) { |
535 // If the fingers have moved too far from their original locations, | 527 // If the fingers have moved too far from their original locations, |
536 // the user can no longer split tap. | 528 // the user can no longer split tap. |
537 ui::TouchEvent* original_touch; | 529 ui::TouchEvent* original_touch; |
538 if (event.touch_id() == last_touch_exploration_->touch_id()) { | 530 if (event.touch_id() == last_touch_exploration_->touch_id()) { |
539 original_touch = last_touch_exploration_.get(); | 531 original_touch = last_touch_exploration_.get(); |
540 } else if (event.touch_id() == initial_press_->touch_id()) { | 532 } else if (event.touch_id() == initial_press_->touch_id()) { |
541 original_touch = initial_press_.get(); | 533 original_touch = initial_press_.get(); |
542 } else { | 534 } else { |
543 NOTREACHED(); | 535 NOTREACHED(); |
544 SET_STATE(WAIT_FOR_NO_FINGERS); | 536 SET_STATE(WAIT_FOR_NO_FINGERS); |
545 return ui::EVENT_REWRITE_DISCARD; | 537 return ui::EVENT_REWRITE_DISCARD; |
546 } | 538 } |
547 // Check the distance between the current finger location and the original | 539 // Check the distance between the current finger location and the original |
548 // location. The slop for this is a bit more generous since keeping two | 540 // location. The slop for this is a bit more generous since keeping two |
549 // fingers in place is a bit harder. If the user has left the slop, the | 541 // fingers in place is a bit harder. If the user has left the slop, the |
550 // split tap press (which was previous dispatched) is lifted with a touch | 542 // user enters the wait state. |
551 // cancelled, and the user enters the wait state. | |
552 if ((event.location_f() - original_touch->location_f()).Length() > | 543 if ((event.location_f() - original_touch->location_f()).Length() > |
553 GetSplitTapTouchSlop()) { | 544 GetSplitTapTouchSlop()) { |
554 std::unique_ptr<ui::TouchEvent> new_event( | |
555 new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, gfx::Point(), | |
556 initial_press_->touch_id(), event.time_stamp())); | |
557 new_event->set_location_f(last_touch_exploration_->location_f()); | |
558 new_event->set_root_location_f(last_touch_exploration_->location_f()); | |
559 new_event->set_flags(event.flags()); | |
560 *rewritten_event = std::move(new_event); | |
561 SET_STATE(WAIT_FOR_NO_FINGERS); | 545 SET_STATE(WAIT_FOR_NO_FINGERS); |
562 return ui::EVENT_REWRITE_REWRITTEN; | |
563 } | 546 } |
564 return ui::EVENT_REWRITE_DISCARD; | 547 return ui::EVENT_REWRITE_DISCARD; |
565 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 548 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
566 // If the touch exploration finger is lifted, there is no option to return | 549 // If the touch exploration finger is lifted, there is no option to return |
567 // to touch explore anymore. The remaining finger acts as a pending | 550 // to touch explore anymore. The remaining finger acts as a pending |
568 // tap or long tap for the last touch explore location. | 551 // tap or long tap for the last touch explore location. |
569 if (event.touch_id() == last_touch_exploration_->touch_id()) { | 552 if (event.touch_id() == last_touch_exploration_->touch_id()) { |
570 SET_STATE(TOUCH_RELEASE_PENDING); | 553 SET_STATE(TOUCH_RELEASE_PENDING); |
571 return EVENT_REWRITE_DISCARD; | 554 return EVENT_REWRITE_DISCARD; |
572 } | 555 } |
573 | 556 |
574 // Continue to release the touch only if the touch explore finger is the | 557 // Continue to release the touch only if the touch explore finger is the |
575 // only finger remaining. | 558 // only finger remaining. |
576 if (current_touch_ids_.size() != 1) | 559 if (current_touch_ids_.size() != 1) |
577 return EVENT_REWRITE_DISCARD; | 560 return EVENT_REWRITE_DISCARD; |
578 | 561 |
579 // Rewrite at location of last touch exploration. | 562 SendSimulatedClick(); |
580 std::unique_ptr<ui::TouchEvent> new_event( | 563 |
581 new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), | |
582 initial_press_->touch_id(), event.time_stamp())); | |
583 new_event->set_location_f(last_touch_exploration_->location_f()); | |
584 new_event->set_root_location_f(last_touch_exploration_->location_f()); | |
585 new_event->set_flags(event.flags()); | |
586 *rewritten_event = std::move(new_event); | |
587 SET_STATE(TOUCH_EXPLORATION); | 564 SET_STATE(TOUCH_EXPLORATION); |
588 EnterTouchToMouseMode(); | 565 EnterTouchToMouseMode(); |
589 return ui::EVENT_REWRITE_REWRITTEN; | 566 return ui::EVENT_REWRITE_DISCARD; |
590 } | 567 } |
591 NOTREACHED(); | 568 NOTREACHED(); |
592 return ui::EVENT_REWRITE_CONTINUE; | 569 return ui::EVENT_REWRITE_CONTINUE; |
593 } | 570 } |
594 | 571 |
595 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( | 572 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( |
596 const ui::TouchEvent& event, | 573 const ui::TouchEvent& event, |
597 std::unique_ptr<ui::Event>* rewritten_event) { | 574 std::unique_ptr<ui::Event>* rewritten_event) { |
598 if (current_touch_ids_.size() == 0) | 575 if (current_touch_ids_.size() == 0) |
599 SET_STATE(NO_FINGERS_DOWN); | 576 SET_STATE(NO_FINGERS_DOWN); |
600 return EVENT_REWRITE_DISCARD; | 577 return EVENT_REWRITE_DISCARD; |
601 } | 578 } |
602 | 579 |
603 void TouchExplorationController::PlaySoundForTimer() { | 580 void TouchExplorationController::PlaySoundForTimer() { |
604 delegate_->PlayVolumeAdjustEarcon(); | 581 delegate_->PlayVolumeAdjustEarcon(); |
605 } | 582 } |
606 | 583 |
| 584 void TouchExplorationController::SendSimulatedClick() { |
| 585 // If we got an anchor point from ChromeVox, send a double-tap gesture |
| 586 // and let ChromeVox handle the click. |
| 587 if (anchor_point_state_ == ANCHOR_POINT_EXPLICITLY_SET) { |
| 588 delegate_->HandleAccessibilityGesture(ui::AX_GESTURE_CLICK); |
| 589 return; |
| 590 } |
| 591 |
| 592 // If we don't have an anchor point, we can't send a simulated click. |
| 593 if (anchor_point_state_ == ANCHOR_POINT_NONE) |
| 594 return; |
| 595 |
| 596 // Otherwise send a simulated press/release at the anchor point. |
| 597 std::unique_ptr<ui::TouchEvent> touch_press; |
| 598 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
| 599 initial_press_->touch_id(), Now())); |
| 600 touch_press->set_location_f(anchor_point_); |
| 601 touch_press->set_root_location_f(anchor_point_); |
| 602 DispatchEvent(touch_press.get()); |
| 603 |
| 604 std::unique_ptr<ui::TouchEvent> touch_release; |
| 605 touch_release.reset(new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| 606 initial_press_->touch_id(), Now())); |
| 607 touch_release->set_location_f(anchor_point_); |
| 608 touch_release->set_root_location_f(anchor_point_); |
| 609 DispatchEvent(touch_release.get()); |
| 610 } |
| 611 |
607 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 612 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
608 const ui::TouchEvent& event, | 613 const ui::TouchEvent& event, |
609 std::unique_ptr<ui::Event>* rewritten_event) { | 614 std::unique_ptr<ui::Event>* rewritten_event) { |
610 // The timer should not fire when sliding. | 615 // The timer should not fire when sliding. |
611 tap_timer_.Stop(); | 616 tap_timer_.Stop(); |
612 | 617 |
613 ui::EventType type = event.type(); | 618 ui::EventType type = event.type(); |
614 // If additional fingers are added before a swipe gesture has been registered, | 619 // If additional fingers are added before a swipe gesture has been registered, |
615 // then wait until all fingers have been lifted. | 620 // then wait until all fingers have been lifted. |
616 if (type == ui::ET_TOUCH_PRESSED || | 621 if (type == ui::ET_TOUCH_PRESSED || |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 } | 711 } |
707 | 712 |
708 void TouchExplorationController::OnTapTimerFired() { | 713 void TouchExplorationController::OnTapTimerFired() { |
709 switch (state_) { | 714 switch (state_) { |
710 case SINGLE_TAP_RELEASED: | 715 case SINGLE_TAP_RELEASED: |
711 SET_STATE(NO_FINGERS_DOWN); | 716 SET_STATE(NO_FINGERS_DOWN); |
712 break; | 717 break; |
713 case TOUCH_EXPLORE_RELEASED: | 718 case TOUCH_EXPLORE_RELEASED: |
714 SET_STATE(NO_FINGERS_DOWN); | 719 SET_STATE(NO_FINGERS_DOWN); |
715 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 720 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| 721 anchor_point_ = last_touch_exploration_->location_f(); |
| 722 anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
716 return; | 723 return; |
717 case DOUBLE_TAP_PENDING: { | 724 case DOUBLE_TAP_PENDING: { |
718 SET_STATE(ONE_FINGER_PASSTHROUGH); | 725 SET_STATE(ONE_FINGER_PASSTHROUGH); |
719 passthrough_offset_ = last_unused_finger_event_->location_f() - | 726 passthrough_offset_ = |
720 last_touch_exploration_->location_f(); | 727 last_unused_finger_event_->location_f() - anchor_point_; |
721 std::unique_ptr<ui::TouchEvent> passthrough_press( | 728 std::unique_ptr<ui::TouchEvent> passthrough_press( |
722 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), | 729 new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
723 last_unused_finger_event_->touch_id(), Now())); | 730 last_unused_finger_event_->touch_id(), Now())); |
724 passthrough_press->set_location_f(last_touch_exploration_->location_f()); | 731 passthrough_press->set_location_f(anchor_point_); |
725 passthrough_press->set_root_location_f( | 732 passthrough_press->set_root_location_f(anchor_point_); |
726 last_touch_exploration_->location_f()); | |
727 DispatchEvent(passthrough_press.get()); | 733 DispatchEvent(passthrough_press.get()); |
728 return; | 734 return; |
729 } | 735 } |
730 case SINGLE_TAP_PRESSED: | 736 case SINGLE_TAP_PRESSED: |
731 if (passthrough_timer_.IsRunning()) | 737 if (passthrough_timer_.IsRunning()) |
732 return; | 738 return; |
733 case GESTURE_IN_PROGRESS: | 739 case GESTURE_IN_PROGRESS: |
734 // If only one finger is down, go into touch exploration. | 740 // If only one finger is down, go into touch exploration. |
735 if (current_touch_ids_.size() == 1) { | 741 if (current_touch_ids_.size() == 1) { |
| 742 anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
736 EnterTouchToMouseMode(); | 743 EnterTouchToMouseMode(); |
737 SET_STATE(TOUCH_EXPLORATION); | 744 SET_STATE(TOUCH_EXPLORATION); |
738 break; | 745 break; |
739 } | 746 } |
740 // Otherwise wait for all fingers to be lifted. | 747 // Otherwise wait for all fingers to be lifted. |
741 SET_STATE(WAIT_FOR_NO_FINGERS); | 748 SET_STATE(WAIT_FOR_NO_FINGERS); |
742 return; | 749 return; |
743 case TWO_FINGER_TAP: | 750 case TWO_FINGER_TAP: |
744 SET_STATE(WAIT_FOR_NO_FINGERS); | 751 SET_STATE(WAIT_FOR_NO_FINGERS); |
745 break; | 752 break; |
746 default: | 753 default: |
747 return; | 754 return; |
748 } | 755 } |
749 EnterTouchToMouseMode(); | 756 EnterTouchToMouseMode(); |
750 std::unique_ptr<ui::Event> mouse_move = CreateMouseMoveEvent( | 757 std::unique_ptr<ui::Event> mouse_move = CreateMouseMoveEvent( |
751 initial_press_->location_f(), initial_press_->flags()); | 758 initial_press_->location_f(), initial_press_->flags()); |
752 DispatchEvent(mouse_move.get()); | 759 DispatchEvent(mouse_move.get()); |
753 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); | 760 last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| 761 anchor_point_ = last_touch_exploration_->location_f(); |
| 762 anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
754 } | 763 } |
755 | 764 |
756 void TouchExplorationController::OnPassthroughTimerFired() { | 765 void TouchExplorationController::OnPassthroughTimerFired() { |
757 // The passthrough timer will only fire if if the user has held a finger in | 766 // The passthrough timer will only fire if if the user has held a finger in |
758 // one of the passthrough corners for the duration of the passthrough timeout. | 767 // one of the passthrough corners for the duration of the passthrough timeout. |
759 | 768 |
760 // Check that initial press isn't null. Also a check that if the initial | 769 // Check that initial press isn't null. Also a check that if the initial |
761 // corner press was released, then it should not be in corner passthrough. | 770 // corner press was released, then it should not be in corner passthrough. |
762 if (!initial_press_ || | 771 if (!initial_press_ || |
763 touch_locations_.find(initial_press_->touch_id()) != | 772 touch_locations_.find(initial_press_->touch_id()) != |
764 touch_locations_.end()) { | 773 touch_locations_.end()) { |
765 LOG(ERROR) << "No initial press or the initial press has been released."; | |
766 } | 774 } |
767 | 775 |
768 gfx::Point location = | 776 gfx::Point location = |
769 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]); | 777 ToRoundedPoint(touch_locations_[initial_press_->touch_id()]); |
770 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); | 778 int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); |
771 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER) | 779 if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER) |
772 return; | 780 return; |
773 | 781 |
774 if (sound_timer_.IsRunning()) | 782 if (sound_timer_.IsRunning()) |
775 sound_timer_.Stop(); | 783 sound_timer_.Stop(); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 return "TWO_FINGER_TAP"; | 1150 return "TWO_FINGER_TAP"; |
1143 } | 1151 } |
1144 return "Not a state"; | 1152 return "Not a state"; |
1145 } | 1153 } |
1146 | 1154 |
1147 float TouchExplorationController::GetSplitTapTouchSlop() { | 1155 float TouchExplorationController::GetSplitTapTouchSlop() { |
1148 return gesture_detector_config_.touch_slop * 3; | 1156 return gesture_detector_config_.touch_slop * 3; |
1149 } | 1157 } |
1150 | 1158 |
1151 } // namespace ui | 1159 } // namespace ui |
OLD | NEW |