Chromium Code Reviews| Index: ui/chromeos/touch_exploration_controller.cc |
| diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc |
| index d4399b1eb45969144fce501748b6a6d8eeca3d21..d26f5ecbd7c3bba5e504f54a5b6890871941d0d1 100644 |
| --- a/ui/chromeos/touch_exploration_controller.cc |
| +++ b/ui/chromeos/touch_exploration_controller.cc |
| @@ -37,6 +37,7 @@ TouchExplorationController::TouchExplorationController( |
| : root_window_(root_window), |
| delegate_(delegate), |
| state_(NO_FINGERS_DOWN), |
| + anchor_point_state_(ANCHOR_POINT_NONE), |
| gesture_provider_(new GestureProviderAura(this, this)), |
| prev_state_(NO_FINGERS_DOWN), |
| VLOG_on_(true), |
| @@ -49,6 +50,15 @@ TouchExplorationController::~TouchExplorationController() { |
| root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); |
| } |
| +void TouchExplorationController::SetTouchAccessibilityAnchorPoint( |
| + const gfx::Point& anchor_point) { |
| + gfx::Point native_point = anchor_point; |
| + root_window_->GetHost()->ConvertPointToNativeScreen(&native_point); |
| + |
| + anchor_point_ = gfx::PointF(native_point.x(), native_point.y()); |
| + anchor_point_state_ = ANCHOR_POINT_EXPLICITLY_SET; |
| +} |
| + |
| ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| const ui::Event& event, |
| std::unique_ptr<ui::Event>* rewritten_event) { |
| @@ -295,6 +305,7 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( |
| SET_STATE(GESTURE_IN_PROGRESS); |
| return InGestureInProgress(event, rewritten_event); |
| } |
| + anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
| EnterTouchToMouseMode(); |
| SET_STATE(TOUCH_EXPLORATION); |
| return InTouchExploration(event, rewritten_event); |
| @@ -315,8 +326,12 @@ TouchExplorationController::InSingleTapOrTouchExploreReleased( |
| return ui::EVENT_REWRITE_DISCARD; |
| } |
| if (type == ui::ET_TOUCH_PRESSED) { |
| - // If there is no touch exploration yet, we can't send a click, so discard. |
| - if (!last_touch_exploration_) { |
| + // If there is no anchor point for synthesized events because the |
| + // user hasn't touch-explored or focused anything yet, we can't |
| + // send a click, so discard. |
| + if (anchor_point_state_ == ANCHOR_POINT_NONE) { |
| + LOG(ERROR) << "*** NO ANCHOR POINT ***"; |
| + |
| tap_timer_.Stop(); |
| return ui::EVENT_REWRITE_DISCARD; |
| } |
| @@ -333,7 +348,8 @@ TouchExplorationController::InSingleTapOrTouchExploreReleased( |
| // will determine the offset. |
| last_unused_finger_event_.reset(new ui::TouchEvent(event)); |
| return ui::EVENT_REWRITE_DISCARD; |
| - } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { |
| + } else if (type == ui::ET_TOUCH_RELEASED && |
| + anchor_point_state_ == ANCHOR_POINT_NONE) { |
| // If the previous press was discarded, we need to also handle its |
| // release. |
| if (current_touch_ids_.size() == 0) { |
| @@ -366,23 +382,10 @@ ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( |
| if (current_touch_ids_.size() != 0) |
| return EVENT_REWRITE_DISCARD; |
| - std::unique_ptr<ui::TouchEvent> touch_press; |
| - touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
| - initial_press_->touch_id(), |
| - event.time_stamp())); |
| - touch_press->set_location_f(last_touch_exploration_->location_f()); |
| - touch_press->set_root_location_f(last_touch_exploration_->location_f()); |
| - DispatchEvent(touch_press.get()); |
| + SendSimulatedClick(); |
| - std::unique_ptr<ui::TouchEvent> new_event( |
| - new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| - initial_press_->touch_id(), event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_flags(event.flags()); |
| - *rewritten_event = std::move(new_event); |
| SET_STATE(NO_FINGERS_DOWN); |
| - return ui::EVENT_REWRITE_REWRITTEN; |
| + return ui::EVENT_REWRITE_DISCARD; |
| } |
| NOTREACHED(); |
| return ui::EVENT_REWRITE_CONTINUE; |
| @@ -398,15 +401,9 @@ ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( |
| if (current_touch_ids_.size() != 0) |
| return EVENT_REWRITE_DISCARD; |
| - std::unique_ptr<ui::TouchEvent> new_event( |
| - new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| - initial_press_->touch_id(), event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_flags(event.flags()); |
| - *rewritten_event = std::move(new_event); |
| + SendSimulatedClick(); |
| SET_STATE(NO_FINGERS_DOWN); |
| - return ui::EVENT_REWRITE_REWRITTEN; |
| + return ui::EVENT_REWRITE_DISCARD; |
| } |
| NOTREACHED(); |
| return ui::EVENT_REWRITE_CONTINUE; |
| @@ -417,18 +414,11 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploration( |
| std::unique_ptr<ui::Event>* rewritten_event) { |
| const ui::EventType type = event.type(); |
| if (type == ui::ET_TOUCH_PRESSED) { |
| - // Handle split-tap. |
| + // Enter split-tap mode. |
| initial_press_.reset(new TouchEvent(event)); |
| tap_timer_.Stop(); |
| - std::unique_ptr<ui::TouchEvent> new_event( |
| - new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), event.touch_id(), |
| - event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_flags(event.flags()); |
| - *rewritten_event = std::move(new_event); |
| SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); |
| - return ui::EVENT_REWRITE_REWRITTEN; |
| + return ui::EVENT_REWRITE_DISCARD; |
| } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| initial_press_.reset(new TouchEvent(event)); |
| StartTapTimer(); |
| @@ -441,6 +431,9 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploration( |
| // Rewrite as a mouse-move event. |
| *rewritten_event = CreateMouseMoveEvent(event.location_f(), event.flags()); |
| last_touch_exploration_.reset(new TouchEvent(event)); |
| + if (anchor_point_state_ != ANCHOR_POINT_EXPLICITLY_SET) |
| + anchor_point_ = last_touch_exploration_->location_f(); |
| + |
| return ui::EVENT_REWRITE_REWRITTEN; |
| } |
| @@ -525,8 +518,8 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( |
| std::unique_ptr<ui::TouchEvent> new_event( |
| new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, gfx::Point(), |
| initial_press_->touch_id(), event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| + new_event->set_location_f(anchor_point_); |
| + new_event->set_root_location_f(anchor_point_); |
| new_event->set_flags(event.flags()); |
| *rewritten_event = std::move(new_event); |
| SET_STATE(WAIT_FOR_NO_FINGERS); |
| @@ -547,19 +540,10 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( |
| // Check the distance between the current finger location and the original |
| // location. The slop for this is a bit more generous since keeping two |
| // fingers in place is a bit harder. If the user has left the slop, the |
| - // split tap press (which was previous dispatched) is lifted with a touch |
| - // cancelled, and the user enters the wait state. |
| + // user enters the wait state. |
| if ((event.location_f() - original_touch->location_f()).Length() > |
| GetSplitTapTouchSlop()) { |
| - std::unique_ptr<ui::TouchEvent> new_event( |
| - new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, gfx::Point(), |
| - initial_press_->touch_id(), event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_flags(event.flags()); |
| - *rewritten_event = std::move(new_event); |
| SET_STATE(WAIT_FOR_NO_FINGERS); |
| - return ui::EVENT_REWRITE_REWRITTEN; |
| } |
| return ui::EVENT_REWRITE_DISCARD; |
| } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| @@ -576,17 +560,11 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( |
| if (current_touch_ids_.size() != 1) |
| return EVENT_REWRITE_DISCARD; |
| - // Rewrite at location of last touch exploration. |
| - std::unique_ptr<ui::TouchEvent> new_event( |
| - new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| - initial_press_->touch_id(), event.time_stamp())); |
| - new_event->set_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_root_location_f(last_touch_exploration_->location_f()); |
| - new_event->set_flags(event.flags()); |
| - *rewritten_event = std::move(new_event); |
| + SendSimulatedClick(); |
| + |
| SET_STATE(TOUCH_EXPLORATION); |
| EnterTouchToMouseMode(); |
| - return ui::EVENT_REWRITE_REWRITTEN; |
| + return ui::EVENT_REWRITE_DISCARD; |
| } |
| NOTREACHED(); |
| return ui::EVENT_REWRITE_CONTINUE; |
| @@ -604,6 +582,34 @@ void TouchExplorationController::PlaySoundForTimer() { |
| delegate_->PlayVolumeAdjustEarcon(); |
| } |
| +void TouchExplorationController::SendSimulatedClick() { |
| + // If we got an anchor point from ChromeVox, send a double-tap gesture |
| + // and let ChromeVox handle the click. |
| + if (anchor_point_state_ == ANCHOR_POINT_EXPLICITLY_SET) { |
|
David Tseng
2016/05/26 22:48:24
I'm not entirely clear when the explicit vs touch
dmazzoni
2016/05/26 22:59:24
Yes, that's right.
If you touch-explore and Chrom
David Tseng
2016/06/01 00:36:15
This is a little surprising to me because a Chrome
|
| + delegate_->HandleAccessibilityGesture(ui::AX_GESTURE_CLICK); |
| + return; |
| + } |
| + |
| + // If we don't have an anchor point, we can't send a simulated click. |
| + if (anchor_point_state_ == ANCHOR_POINT_NONE) |
| + return; |
| + |
| + // Otherwise send a simulated press/release at the anchor point. |
| + std::unique_ptr<ui::TouchEvent> touch_press; |
| + touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
| + initial_press_->touch_id(), Now())); |
| + touch_press->set_location_f(anchor_point_); |
| + touch_press->set_root_location_f(anchor_point_); |
| + DispatchEvent(touch_press.get()); |
| + |
| + std::unique_ptr<ui::TouchEvent> touch_release; |
| + touch_release.reset(new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| + initial_press_->touch_id(), Now())); |
| + touch_release->set_location_f(anchor_point_); |
| + touch_release->set_root_location_f(anchor_point_); |
| + DispatchEvent(touch_release.get()); |
| +} |
| + |
| ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
| const ui::TouchEvent& event, |
| std::unique_ptr<ui::Event>* rewritten_event) { |
| @@ -706,6 +712,7 @@ void TouchExplorationController::StartTapTimer() { |
| } |
| void TouchExplorationController::OnTapTimerFired() { |
| + LOG(ERROR) << "** OnTapTimerFired **"; |
|
David Tseng
2016/05/26 22:48:24
nit: remove
dmazzoni
2016/05/26 22:59:24
Done.
|
| switch (state_) { |
| case SINGLE_TAP_RELEASED: |
| SET_STATE(NO_FINGERS_DOWN); |
| @@ -713,17 +720,18 @@ void TouchExplorationController::OnTapTimerFired() { |
| case TOUCH_EXPLORE_RELEASED: |
| SET_STATE(NO_FINGERS_DOWN); |
| last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| + anchor_point_ = last_touch_exploration_->location_f(); |
| + anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
| return; |
| case DOUBLE_TAP_PENDING: { |
| SET_STATE(ONE_FINGER_PASSTHROUGH); |
| - passthrough_offset_ = last_unused_finger_event_->location_f() - |
| - last_touch_exploration_->location_f(); |
| + passthrough_offset_ = |
| + last_unused_finger_event_->location_f() - anchor_point_; |
| std::unique_ptr<ui::TouchEvent> passthrough_press( |
| new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
| last_unused_finger_event_->touch_id(), Now())); |
| - passthrough_press->set_location_f(last_touch_exploration_->location_f()); |
| - passthrough_press->set_root_location_f( |
| - last_touch_exploration_->location_f()); |
| + passthrough_press->set_location_f(anchor_point_); |
| + passthrough_press->set_root_location_f(anchor_point_); |
| DispatchEvent(passthrough_press.get()); |
| return; |
| } |
| @@ -733,6 +741,7 @@ void TouchExplorationController::OnTapTimerFired() { |
| case GESTURE_IN_PROGRESS: |
| // If only one finger is down, go into touch exploration. |
| if (current_touch_ids_.size() == 1) { |
| + anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
| EnterTouchToMouseMode(); |
| SET_STATE(TOUCH_EXPLORATION); |
| break; |
| @@ -751,6 +760,8 @@ void TouchExplorationController::OnTapTimerFired() { |
| initial_press_->location_f(), initial_press_->flags()); |
| DispatchEvent(mouse_move.get()); |
| last_touch_exploration_.reset(new TouchEvent(*initial_press_)); |
| + anchor_point_ = last_touch_exploration_->location_f(); |
| + anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION; |
| } |
| void TouchExplorationController::OnPassthroughTimerFired() { |
| @@ -762,7 +773,6 @@ void TouchExplorationController::OnPassthroughTimerFired() { |
| if (!initial_press_ || |
| touch_locations_.find(initial_press_->touch_id()) != |
| touch_locations_.end()) { |
| - LOG(ERROR) << "No initial press or the initial press has been released."; |
| } |
| gfx::Point location = |