1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/chromeos/touch_exploration_controller.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/logging.h" 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/default_tick_clock.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/aura/client/cursor_client.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/aura/window.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/aura/window_tree_host.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/events/event.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/events/event_processor.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/event_utils.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/geometry/rect.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#define SET_STATE(state) SetState(state, __func__) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define VLOG_EVENT(event) if (VLOG_IS_ON(0)) VlogEvent(event, __func__) 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace ui { 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Delay between adjustment sounds. 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150); 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Delay before corner passthrough activates. 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const base::TimeDelta kCornerPassthroughDelay = 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeDelta::FromMilliseconds(700); 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// In ChromeOS, VKEY_LWIN is synonymous for the search key. 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN; 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TouchExplorationController::TouchExplorationController( 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) aura::Window* root_window, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TouchExplorationControllerDelegate* delegate) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : root_window_(root_window), 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_(delegate), 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) state_(NO_FINGERS_DOWN), 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_(new GestureProviderAura(this)), 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prev_state_(NO_FINGERS_DOWN), 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG_on_(true), 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tick_clock_(NULL) { 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CHECK(root_window); 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) root_window->GetHost()->GetEventSource()->AddEventRewriter(this); 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) InitializeSwipeGestureMaps(); 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TouchExplorationController::~TouchExplorationController() { 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this); 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::RewriteEvent( 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ui::Event& event, 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!event.IsTouchEvent()) { 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event.IsKeyEvent()) { 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(0) << "\nKeyboard event: " << key_event.name() 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << "\n Key code: " << key_event.key_code() 646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ", Flags: " << key_event.flags() 656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ", Is char: " << key_event.is_char(); 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event); 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the tap timer should have fired by now but hasn't, run it now and 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // stop the timer. This is important so that behavior is consistent with 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the timestamps of the events, and not dependent on the granularity of 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the timer. 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (tap_timer_.IsRunning() && 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) touch_event.time_stamp() - initial_press_->time_stamp() > 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gesture_detector_config_.double_tap_timeout) { 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tap_timer_.Stop(); 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OnTapTimerFired(); 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Note: this may change the state. We should now continue and process 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // this event under this new state. 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (passthrough_timer_.IsRunning() && 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.time_stamp() - initial_press_->time_stamp() > 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_detector_config_.longpress_timeout) { 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) passthrough_timer_.Stop(); 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnPassthroughTimerFired(); 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ui::EventType type = touch_event.type(); 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const gfx::PointF& location = touch_event.location_f(); 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int touch_id = touch_event.touch_id(); 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Always update touch ids and touch locations, so we can use those 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // no matter what state we're in. 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) current_touch_ids_.push_back(touch_id); 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location)); 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<int>::iterator it = std::find( 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Can happen if touch exploration is enabled while fingers were down. 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it == current_touch_ids_.end()) 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) current_touch_ids_.erase(it); 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) touch_locations_.erase(touch_id); 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_MOVED) { 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<int>::iterator it = std::find( 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) current_touch_ids_.begin(), current_touch_ids_.end(), touch_id); 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Can happen if touch exploration is enabled while fingers were down. 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it == current_touch_ids_.end()) 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) touch_locations_[*it] = location; 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED() << "Unexpected event type received: " << event.name(); 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VLOG_EVENT(touch_event); 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // In order to avoid accidentally double tapping when moving off the edge 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // of the screen, the state will be rewritten to NoFingersDown. 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) && 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FindEdgesWithinBounds(touch_event.location(), kLeavingScreenEdge) != 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NO_EDGE) { 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VLOG_on_) 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(0) << "Leaving screen"; 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Indicates to the user that they are leaving the screen. 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayExitScreenEarcon(); 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 0) { 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VLOG_on_) { 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(0) << "Reset to no fingers in Rewrite event because the touch " 1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "release or cancel was on the edge of the screen."; 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the user is in a gesture state, or if there is a possiblity that the 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // user will enter it in the future, we send the event to the gesture 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // provider so it can keep track of the state of the fingers. When the user 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // leaves one of these states, SET_STATE will set the gesture provider to 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // NULL. 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (gesture_provider_.get()) { 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_->OnTouchEvent(touch_event); 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_->OnTouchEventAck(false); 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ProcessGestureEvents(); 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The rest of the processing depends on what state we're in. 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (state_) { 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case NO_FINGERS_DOWN: 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return InNoFingersDown(touch_event, rewritten_event); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case SINGLE_TAP_PRESSED: 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return InSingleTapPressed(touch_event, rewritten_event); 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case SINGLE_TAP_RELEASED: 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case TOUCH_EXPLORE_RELEASED: 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return InSingleTapOrTouchExploreReleased(touch_event, rewritten_event); 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case DOUBLE_TAP_PENDING: 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return InDoubleTapPending(touch_event, rewritten_event); 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case TOUCH_RELEASE_PENDING: 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return InTouchReleasePending(touch_event, rewritten_event); 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case TOUCH_EXPLORATION: 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return InTouchExploration(touch_event, rewritten_event); 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case GESTURE_IN_PROGRESS: 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return InGestureInProgress(touch_event, rewritten_event); 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case TOUCH_EXPLORE_SECOND_PRESS: 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return InTouchExploreSecondPress(touch_event, rewritten_event); 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case SLIDE_GESTURE: 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return InSlideGesture(touch_event, rewritten_event); 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case ONE_FINGER_PASSTHROUGH: 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return InOneFingerPassthrough(touch_event, rewritten_event); 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case CORNER_PASSTHROUGH: 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return InCornerPassthrough(touch_event, rewritten_event); 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case WAIT_FOR_NO_FINGERS: 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return InWaitForNoFingers(touch_event, rewritten_event); 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TWO_FINGER_TAP: 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return InTwoFingerTap(touch_event, rewritten_event); 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent( 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::Event& last_event, scoped_ptr<ui::Event>* new_event) { 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InNoFingersDown( 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::EventType type = event.type(); 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (type != ui::ET_TOUCH_PRESSED) { 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED() << "Unexpected event type received: " << event.name(); 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the user enters the screen from the edge then send an earcon. 2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int edge = FindEdgesWithinBounds(event.location(), kLeavingScreenEdge); 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (edge != NO_EDGE) 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayEnterScreenEarcon(); 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int location = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the press was at a corner, the user might go into corner passthrough 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // instead. 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool in_a_bottom_corner = 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location); 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (in_a_bottom_corner) { 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) passthrough_timer_.Start( 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_detector_config_.longpress_timeout, 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) this, 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &TouchExplorationController::OnPassthroughTimerFired); 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) initial_press_.reset(new TouchEvent(event)); 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) initial_presses_[event.touch_id()] = event.location(); 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) last_unused_finger_event_.reset(new TouchEvent(event)); 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) StartTapTimer(); 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(SINGLE_TAP_PRESSED); 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed( 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::TouchEvent& event, scoped_ptr<ui::Event>* rewritten_event) { 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::EventType type = event.type(); 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int location = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); 2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool in_a_bottom_corner = 2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER); 2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the event is from the initial press and the location is no longer in the 2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // corner, then we are not waiting for a corner passthrough anymore. 2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event.touch_id() == initial_press_->touch_id() && !in_a_bottom_corner) { 2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (passthrough_timer_.IsRunning()) { 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) passthrough_timer_.Stop(); 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Since the long press timer has been running, it is possible that the 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // tap timer has timed out before the long press timer has. If the tap 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // timer timeout has elapsed, then fire the tap timer. 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event.time_stamp() - initial_press_->time_stamp() > 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_detector_config_.double_tap_timeout) { 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnTapTimerFired(); 2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) initial_presses_[event.touch_id()] = event.location(); 2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TWO_FINGER_TAP); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EVENT_REWRITE_DISCARD; 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (passthrough_timer_.IsRunning()) 2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) passthrough_timer_.Stop(); 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (current_touch_ids_.size() == 0 && 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.touch_id() == initial_press_->touch_id()) { 2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(SINGLE_TAP_RELEASED); 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (current_touch_ids_.size() == 0) { 2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EVENT_REWRITE_DISCARD; 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_MOVED) { 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float distance = (event.location() - initial_press_->location()).Length(); 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the user does not move far enough from the original position, then the 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // resulting movement should not be considered to be a deliberate gesture or 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // touch exploration. 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (distance <= gesture_detector_config_.touch_slop) 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return EVENT_REWRITE_DISCARD; 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float delta_time = 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (event.time_stamp() - initial_press_->time_stamp()).InSecondsF(); 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float velocity = distance / delta_time; 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (VLOG_on_) { 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(0) << "\n Delta time: " << delta_time << "\n Distance: " << distance 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\n Velocity of click: " << velocity 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\n Minimum swipe velocity: " 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << gesture_detector_config_.minimum_swipe_velocity; 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Change to slide gesture if the slide occurred at the right edge. 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int edge = FindEdgesWithinBounds(event.location(), kMaxDistanceFromEdge); 2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (edge & RIGHT_EDGE && edge != BOTTOM_RIGHT_CORNER) { 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(SLIDE_GESTURE); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return InSlideGesture(event, rewritten_event); 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the user moves fast enough from the initial touch location, start 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // gesture detection. Otherwise, jump to the touch exploration mode early. 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (velocity > gesture_detector_config_.minimum_swipe_velocity) { 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(GESTURE_IN_PROGRESS); 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return InGestureInProgress(event, rewritten_event); 295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EnterTouchToMouseMode(); 2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_EXPLORATION); 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return InTouchExploration(event, rewritten_event); 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdochui::EventRewriteStatus 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TouchExplorationController::InSingleTapOrTouchExploreReleased( 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& event, 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ui::Event>* rewritten_event) { 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::EventType type = event.type(); 3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If there is more than one finger down, then discard to wait until no 3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // fingers are down. 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_touch_ids_.size() > 1) { 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ui::EVENT_REWRITE_DISCARD; 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 31603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If there is no touch exploration yet, we can't send a click, so discard. 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!last_touch_exploration_) { 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tap_timer_.Stop(); 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This is the second tap in a double-tap (or double tap-hold). 32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // We set the tap timer. If it fires before the user lifts their finger, 32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // one-finger passthrough begins. Otherwise, there is a touch press and 32403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // release at the location of the last touch exploration. 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(DOUBLE_TAP_PENDING); 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The old tap timer (from the initial click) is stopped if it is still 32703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // going, and the new one is set. 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tap_timer_.Stop(); 32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StartTapTimer(); 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This will update as the finger moves before a possible passthrough, and 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // will determine the offset. 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_unused_finger_event_.reset(new ui::TouchEvent(event)); 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 33403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED && !last_touch_exploration_) { 33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If the previous press was discarded, we need to also handle its 33603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // release. 33703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (current_touch_ids_.size() == 0) { 33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (type == ui::ET_TOUCH_MOVED) { 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ui::EVENT_REWRITE_DISCARD; 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending( 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ui::TouchEvent& event, 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::EventType type = event.type(); 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (type == ui::ET_TOUCH_MOVED) { 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If the user moves far enough from the initial touch location (outside 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the "slop" region, jump to passthrough mode early. 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float delta = (event.location() - initial_press_->location()).Length(); 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (delta > gesture_detector_config_.touch_slop) { 35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) tap_timer_.Stop(); 36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) OnTapTimerFired(); 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EVENT_REWRITE_DISCARD; 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (current_touch_ids_.size() != 0) 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EVENT_REWRITE_DISCARD; 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ui::TouchEvent> touch_press; 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_touch_exploration_->location(), 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) initial_press_->touch_id(), 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.time_stamp())); 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DispatchEvent(touch_press.get()); 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rewritten_event->reset( 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) last_touch_exploration_->location(), 3776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) initial_press_->touch_id(), 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event.time_stamp())); 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ui::TouchEvent& event, 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ui::EventType type = event.type(); 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { 392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (current_touch_ids_.size() != 0) 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EVENT_REWRITE_DISCARD; 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rewritten_event->reset( 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_touch_exploration_->location(), 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) initial_press_->touch_id(), 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.time_stamp())); 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 4036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 4066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InTouchExploration( 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& event, 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ui::Event>* rewritten_event) { 413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::EventType type = event.type(); 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Handle split-tap. 416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) initial_press_.reset(new TouchEvent(event)); 4176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tap_timer_.Stop(); 418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rewritten_event->reset( 419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) last_touch_exploration_->location(), 421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event.touch_id(), 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event.time_stamp())); 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 4246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch initial_press_.reset(new TouchEvent(event)); 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) StartTapTimer(); 4296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_EXPLORE_RELEASED); 430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type != ui::ET_TOUCH_MOVED) { 4316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Rewrite as a mouse-move event. 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *rewritten_event = CreateMouseMoveEvent(event.location(), event.flags()); 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) last_touch_exploration_.reset(new TouchEvent(event)); 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdochui::EventRewriteStatus TouchExplorationController::InGestureInProgress( 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& event, 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ui::Event>* rewritten_event) { 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The events were sent to the gesture provider in RewriteEvent already. 4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If no gesture is registered before the tap timer times out, the state 4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // will change to "wait for no fingers down" or "touch exploration" depending 4476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // on the number of fingers down, and this function will stop being called. 4486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 0) { 4496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 4526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough( 4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::TouchEvent& event, 4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::EventType type = event.type(); 4586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the first finger has left the corner, then exit passthrough. 4606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event.touch_id() == initial_press_->touch_id()) { 4616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int edges = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); 4626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool in_a_bottom_corner = (edges == BOTTOM_LEFT_CORNER) || 4636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (edges == BOTTOM_RIGHT_CORNER); 4646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner) 4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (current_touch_ids_.size() == 0) { 4686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 4696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 4746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) rewritten_event->reset(new ui::TouchEvent( 4766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) type, event.location(), event.touch_id(), event.time_stamp())); 4776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 4786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 0) 4806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 4816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough( 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& event, 487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ui::Event>* rewritten_event) { 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (event.touch_id() != initial_press_->touch_id()) { 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (current_touch_ids_.size() == 0) { 4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rewritten_event->reset( 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new ui::TouchEvent(event.type(), 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.location() - passthrough_offset_, 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.touch_id(), 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.time_stamp())); 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (*rewritten_event)->set_flags(event.flags()); 501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_touch_ids_.size() == 0) { 5026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ui::EVENT_REWRITE_REWRITTEN; 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress( 508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ui::TouchEvent& event, 509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ui::EventType type = event.type(); 511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::PointF location = event.location_f(); 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 5136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // A third finger being pressed means that a split tap can no longer go 5146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // through. The user enters the wait state, Since there has already been 5156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // a press dispatched when split tap began, the touch needs to be 5166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // cancelled. 5176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) rewritten_event->reset( 5186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, 5196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) last_touch_exploration_->location(), 5206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) initial_press_->touch_id(), 5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.time_stamp())); 5226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 5236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 5246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_MOVED) { 5266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the fingers have moved too far from their original locations, 5276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // the user can no longer split tap. 5286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::TouchEvent* original_touch; 5296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event.touch_id() == last_touch_exploration_->touch_id()) 5306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) original_touch = last_touch_exploration_.get(); 5316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else if (event.touch_id() == initial_press_->touch_id()) 5326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) original_touch = initial_press_.get(); 5336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else { 5346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 5356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 5366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 5376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 5386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Check the distance between the current finger location and the original 5396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // location. The slop for this is a bit more generous since keeping two 5406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // fingers in place is a bit harder. If the user has left the slop, the 5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // split tap press (which was previous dispatched) is lifted with a touch 5426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // cancelled, and the user enters the wait state. 5436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((event.location() - original_touch->location()).Length() > 5446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetSplitTapTouchSlop()) { 5456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) rewritten_event->reset( 5466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_CANCELLED, 5476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) last_touch_exploration_->location(), 5486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) initial_press_->touch_id(), 5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event.time_stamp())); 5506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 5516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 5526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 5536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { 556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the touch exploration finger is lifted, there is no option to return 557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // to touch explore anymore. The remaining finger acts as a pending 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // tap or long tap for the last touch explore location. 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (event.touch_id() == last_touch_exploration_->touch_id()){ 5606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_RELEASE_PENDING); 561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EVENT_REWRITE_DISCARD; 562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Continue to release the touch only if the touch explore finger is the 565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // only finger remaining. 566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (current_touch_ids_.size() != 1) 567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EVENT_REWRITE_DISCARD; 568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Rewrite at location of last touch exploration. 570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rewritten_event->reset( 571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_RELEASED, 572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) last_touch_exploration_->location(), 573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) initial_press_->touch_id(), 574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event.time_stamp())); 575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*rewritten_event)->set_flags(event.flags()); 5766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_EXPLORATION); 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EnterTouchToMouseMode(); 578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::EVENT_REWRITE_REWRITTEN; 579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 5806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ui::EVENT_REWRITE_CONTINUE; 582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( 585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ui::TouchEvent& event, 586116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ui::Event>* rewritten_event) { 5876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 0) 5886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return EVENT_REWRITE_DISCARD; 590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchExplorationController::PlaySoundForTimer() { 5936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayVolumeAdjustEarcon(); 5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InSlideGesture( 5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ui::TouchEvent& event, 5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The timer should not fire when sliding. 6006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tap_timer_.Stop(); 6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::EventType type = event.type(); 6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If additional fingers are added before a swipe gesture has been registered, 6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // then wait until all fingers have been lifted. 6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED || 6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event.touch_id() != initial_press_->touch_id()) { 6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sound_timer_.IsRunning()) 6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sound_timer_.Stop(); 6096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EVENT_REWRITE_DISCARD; 6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // There should not be more than one finger down. 6146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(current_touch_ids_.size() <= 1); 6156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Allows user to return to the edge to adjust the sound if they have left the 6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // boundaries. 6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int edge = FindEdgesWithinBounds(event.location(), kSlopDistanceFromEdge); 6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!(edge & RIGHT_EDGE) && (type != ui::ET_TOUCH_RELEASED)) { 6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sound_timer_.IsRunning()) { 6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sound_timer_.Stop(); 6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EVENT_REWRITE_DISCARD; 6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This can occur if the user leaves the screen edge and then returns to it to 6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // continue adjusting the sound. 6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!sound_timer_.IsRunning()) { 6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sound_timer_.Start(FROM_HERE, 6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kSoundDelay, 6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this, 6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &ui::TouchExplorationController::PlaySoundForTimer); 6336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayVolumeAdjustEarcon(); 6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 0) { 6376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 6416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap( 6436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::TouchEvent& event, 6446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<ui::Event>* rewritten_event) { 6456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::EventType type = event.type(); 6466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (type == ui::ET_TOUCH_PRESSED) { 6476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // This is now a three finger gesture. 6486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(GESTURE_IN_PROGRESS); 6496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 6516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (type == ui::ET_TOUCH_MOVED) { 6536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Determine if it was a swipe. 6546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gfx::Point original_location = initial_presses_[event.touch_id()]; 6556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) float distance = (event.location() - original_location).Length(); 6566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If the user moves too far from the original position, consider the 6576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // movement a swipe. 6586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (distance > gesture_detector_config_.touch_slop) { 6596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(GESTURE_IN_PROGRESS); 6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() != 0) 6656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (type == ui::ET_TOUCH_RELEASED) { 6686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // In ChromeVox, pressing control will stop ChromeVox from speaking. 6696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent control_down( 6706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); 6716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent control_up(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ui::EF_NONE); 6726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 6736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&control_down); 6746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&control_up); 6756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 6766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EVENT_REWRITE_DISCARD; 6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::TimeDelta TouchExplorationController::Now() { 6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (tick_clock_) { 6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This is the same as what EventTimeForNow() does, but here we do it 6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // with a clock that can be replaced with a simulated clock for tests. 6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return base::TimeDelta::FromInternalValue( 6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tick_clock_->NowTicks().ToInternalValue()); 6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ui::EventTimeForNow(); 6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchExplorationController::StartTapTimer() { 6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tap_timer_.Start(FROM_HERE, 6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gesture_detector_config_.double_tap_timeout, 6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this, 6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &TouchExplorationController::OnTapTimerFired); 6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 698116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TouchExplorationController::OnTapTimerFired() { 699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (state_) { 700116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case SINGLE_TAP_RELEASED: 7016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case TOUCH_EXPLORE_RELEASED: 7046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(NO_FINGERS_DOWN); 705116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 706116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 70703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case DOUBLE_TAP_PENDING: { 70803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SET_STATE(ONE_FINGER_PASSTHROUGH); 70903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) passthrough_offset_ = last_unused_finger_event_->location() - 71003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) last_touch_exploration_->location(); 71103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<ui::TouchEvent> passthrough_press( 71203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new ui::TouchEvent(ui::ET_TOUCH_PRESSED, 71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) last_touch_exploration_->location(), 71403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) last_unused_finger_event_->touch_id(), 71503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Now())); 71603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchEvent(passthrough_press.get()); 71703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 71803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 7196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case SINGLE_TAP_PRESSED: 7206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (passthrough_timer_.IsRunning()) 7216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 7226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case GESTURE_IN_PROGRESS: 7236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If only one finger is down, go into touch exploration. 7246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (current_touch_ids_.size() == 1) { 7256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EnterTouchToMouseMode(); 7266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(TOUCH_EXPLORATION); 7276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 7286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 7296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Otherwise wait for all fingers to be lifted. 7306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 7316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 7326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TWO_FINGER_TAP: 7336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 7346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 7356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) default: 7366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 7376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 7386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EnterTouchToMouseMode(); 7396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<ui::Event> mouse_move = 7406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CreateMouseMoveEvent(initial_press_->location(), initial_press_->flags()); 7416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(mouse_move.get()); 7426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) last_touch_exploration_.reset(new TouchEvent(*initial_press_)); 7436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 7446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 7456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void TouchExplorationController::OnPassthroughTimerFired() { 74603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The passthrough timer will only fire if if the user has held a finger in 74703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // one of the passthrough corners for the duration of the passthrough timeout. 7486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 74903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Check that initial press isn't null. Also a check that if the initial 75003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // corner press was released, then it should not be in corner passthrough. 75103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!initial_press_ || 75203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) touch_locations_.find(initial_press_->touch_id()) != 75303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) touch_locations_.end()) { 75403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(ERROR) << "No initial press or the initial press has been released."; 755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 75603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 75703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Point location = 75803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ToRoundedPoint(touch_locations_[initial_press_->touch_id()]); 75903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int corner = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); 76003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER) 76103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 76203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 7636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (sound_timer_.IsRunning()) 7646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sound_timer_.Stop(); 7656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayPassthroughEarcon(); 76603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SET_STATE(CORNER_PASSTHROUGH); 76703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void TouchExplorationController::DispatchEvent(ui::Event* event) { 771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ui::EventDispatchDetails result ALLOW_UNUSED = 772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) root_window_->GetHost()->dispatcher()->OnEventFromSource(event); 773010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 774010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This is an override for a function that is only called for timer-based events 7766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// like long press. Events that are created synchronously as a result of 7776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// certain touch events are added to the vector accessible via 7786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// GetAndResetPendingGestures(). We only care about swipes (which are created 7796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// synchronously), so we ignore this callback. 7806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void TouchExplorationController::OnGestureEvent(ui::GestureEvent* gesture) { 781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 783116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TouchExplorationController::ProcessGestureEvents() { 784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScopedVector<ui::GestureEvent> > gestures( 7856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_->GetAndResetPendingGestures()); 786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (gestures) { 787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<GestureEvent>::iterator i = gestures->begin(); 788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch i != gestures->end(); 789116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++i) { 7906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((*i)->type() == ui::ET_GESTURE_SWIPE && 7916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) state_ == GESTURE_IN_PROGRESS) { 7926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnSwipeEvent(*i); 7936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The tap timer to leave gesture state is ended, and we now wait for 7946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // all fingers to be released. 7956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tap_timer_.Stop(); 7966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SET_STATE(WAIT_FOR_NO_FINGERS); 7976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 7986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 7996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (state_ == SLIDE_GESTURE && (*i)->IsScrollGestureEvent()) { 8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SideSlideControl(*i); 8016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 802116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 804116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 805116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchExplorationController::SideSlideControl(ui::GestureEvent* gesture) { 8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::EventType type = gesture->type(); 8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == ET_GESTURE_SCROLL_BEGIN) { 8106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayVolumeAdjustEarcon(); 8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == ET_GESTURE_SCROLL_END) { 8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (sound_timer_.IsRunning()) 8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sound_timer_.Stop(); 8166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->PlayVolumeAdjustEarcon(); 8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If the user is in the corner of the right side of the screen, the volume 8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // will be automatically set to 100% or muted depending on which corner they 8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // are in. Otherwise, the user will be able to adjust the volume by sliding 8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // their finger along the right side of the screen. Volume is relative to 8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // where they are on the right side of the screen. 8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Point location = gesture->location(); 8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int edge = FindEdgesWithinBounds(location, kSlopDistanceFromEdge); 8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!(edge & RIGHT_EDGE)) 8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (edge & TOP_EDGE) { 8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->SetOutputLevel(100); 8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (edge & BOTTOM_EDGE) { 8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->SetOutputLevel(0); 8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) location = gesture->location(); 8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) root_window_->GetHost()->ConvertPointFromNativeScreen(&location); 8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float volume_adjust_height = 8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) root_window_->bounds().height() - 2 * kMaxDistanceFromEdge; 8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float ratio = (location.y() - kMaxDistanceFromEdge) / volume_adjust_height; 8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float volume = 100 - 100 * ratio; 8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (VLOG_on_) { 8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(0) << "\n Volume = " << volume 8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\n Location = " << location.ToString() 8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\n Bounds = " << root_window_->bounds().right(); 8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->SetOutputLevel(int(volume)); 8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 852116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) { 853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // A swipe gesture contains details for the direction in which the swipe 8546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // occurred. TODO(evy) : Research which swipe results users most want and 8556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // remap these swipes to the best events. Hopefully in the near future 8566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // there will also be a menu for users to pick custom mappings. 857116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GestureEventDetails event_details = swipe_gesture->details(); 8586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int num_fingers = event_details.touch_points(); 8596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if(VLOG_on_) 8606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(0) << "\nSwipe with " << num_fingers << " fingers."; 8616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 8626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (num_fingers > 4) 863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 8646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 8656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (event_details.swipe_left() && 8666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !left_swipe_gestures_[num_fingers].is_null()) { 8676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_swipe_gestures_[num_fingers].Run(); 8686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (event_details.swipe_right() && 8696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !right_swipe_gestures_[num_fingers].is_null()) { 8706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_swipe_gestures_[num_fingers].Run(); 8716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (event_details.swipe_up() && 8726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !up_swipe_gestures_[num_fingers].is_null()) { 8736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) up_swipe_gestures_[num_fingers].Run(); 8746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (event_details.swipe_down() && 8756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !down_swipe_gestures_[num_fingers].is_null()) { 8766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) down_swipe_gestures_[num_fingers].Run(); 877116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 879116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int TouchExplorationController::FindEdgesWithinBounds(gfx::Point point, 8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float bounds) { 8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Since GetBoundsInScreen is in DIPs but point is not, then point needs to be 8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // converted. 8845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) root_window_->GetHost()->ConvertPointFromNativeScreen(&point); 8855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Rect window = root_window_->GetBoundsInScreen(); 8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float left_edge_limit = window.x() + bounds; 8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float right_edge_limit = window.right() - bounds; 8895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float top_edge_limit = window.y() + bounds; 8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float bottom_edge_limit = window.bottom() - bounds; 8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Bitwise manipulation in order to determine where on the screen the point 8935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // lies. If more than one bit is turned on, then it is a corner where the two 8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // bit/edges intersect. Otherwise, if no bits are turned on, the point must be 8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // in the center of the screen. 8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int result = NO_EDGE; 8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (point.x() < left_edge_limit) 8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result |= LEFT_EDGE; 8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (point.x() > right_edge_limit) 9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result |= RIGHT_EDGE; 9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (point.y() < top_edge_limit) 9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result |= TOP_EDGE; 9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (point.y() > bottom_edge_limit) 9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result |= BOTTOM_EDGE; 9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result; 9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 908116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TouchExplorationController::DispatchShiftSearchKeyEvent( 9096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::KeyboardCode third_key) { 910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // In order to activate the shortcut shift+search+<arrow key> 911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // three KeyPressed events must be dispatched in succession along 912116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // with three KeyReleased events. 9136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent shift_down( 9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN); 9166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent search_down( 9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::ET_KEY_PRESSED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); 9186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent third_key_down(ui::ET_KEY_PRESSED, third_key, ui::EF_SHIFT_DOWN); 919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 9206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent third_key_up(ui::ET_KEY_RELEASED, third_key, ui::EF_SHIFT_DOWN); 9216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent search_up( 9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::ET_KEY_RELEASED, kChromeOSSearchKey, ui::EF_SHIFT_DOWN); 9236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui ::KeyEvent shift_up(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE); 924116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchEvent(&shift_down); 926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchEvent(&search_down); 9276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&third_key_down); 9286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&third_key_up); 929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchEvent(&search_up); 930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchEvent(&shift_up); 931116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 932116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 9336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::Closure TouchExplorationController::BindShiftSearchKeyEvent( 9346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::KeyboardCode third_key) { 9356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return base::Bind(&TouchExplorationController::DispatchShiftSearchKeyEvent, 9366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Unretained(this), 9376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) third_key); 9386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 9396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void TouchExplorationController::DispatchKeyWithFlags( 9416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::KeyboardCode key, 9426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int flags) { 9436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags); 9446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags); 9456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&key_down); 9466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DispatchEvent(&key_up); 9476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if(VLOG_on_) { 9486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(0) << "\nKey down: key code : " << key_down.key_code() 9496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ", flags: " << key_down.flags() 9506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << "\nKey up: key code : " << key_up.key_code() 9516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ", flags: " << key_up.flags(); 9526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 9536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 9546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::Closure TouchExplorationController::BindKeyEventWithFlags( 9566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::KeyboardCode key, 9576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int flags) { 9586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return base::Bind(&TouchExplorationController::DispatchKeyWithFlags, 9596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Unretained(this), 9606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) key, 9616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) flags); 9626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 9636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 964010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<ui::Event> TouchExplorationController::CreateMouseMoveEvent( 965010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const gfx::PointF& location, 966010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int flags) { 9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The "synthesized" flag should be set on all events that don't have a 9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // backing native event. 9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) flags |= ui::EF_IS_SYNTHESIZED; 9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This flag is used to identify mouse move events that were generated from 9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // touch exploration in Chrome code. 9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) flags |= ui::EF_TOUCH_ACCESSIBILITY; 9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(dmazzoni) http://crbug.com/391008 - get rid of this hack. 9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This is a short-term workaround for the limitation that we're using 9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the ChromeVox content script to process touch exploration events, but 9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ChromeVox needs a way to distinguish between a real mouse move and a 9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // mouse move generated from touch exploration, so we have touch exploration 9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // pretend that the command key was down (which becomes the "meta" key in 9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // JavaScript). We can remove this hack when the ChromeVox content script 9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // goes away and native accessibility code sends a touch exploration 9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // event to the new ChromeVox background page via the automation api. 9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) flags |= ui::EF_COMMAND_DOWN; 9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 986010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return scoped_ptr<ui::Event>( 9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new ui::MouseEvent(ui::ET_MOUSE_MOVED, location, location, flags, 0)); 988010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 989010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 990010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void TouchExplorationController::EnterTouchToMouseMode() { 991010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::client::CursorClient* cursor_client = 992010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::client::GetCursorClient(root_window_); 993010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (cursor_client && !cursor_client->IsMouseEventsEnabled()) 994010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) cursor_client->EnableMouseEvents(); 995010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (cursor_client && cursor_client->IsCursorVisible()) 996010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) cursor_client->HideCursor(); 997010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 998010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 9996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void TouchExplorationController::SetState(State new_state, 10006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const char* function_name) { 10016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) state_ = new_state; 10026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VlogState(function_name); 10036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // These are the states the user can be in that will never result in a 10046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // gesture before the user returns to NO_FINGERS_DOWN. Therefore, if the 10056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // gesture provider still exists, it's reset to NULL until the user returns 10066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // to NO_FINGERS_DOWN. 10076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (new_state) { 10086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case SINGLE_TAP_RELEASED: 10096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TOUCH_EXPLORE_RELEASED: 10106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DOUBLE_TAP_PENDING: 10116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TOUCH_RELEASE_PENDING: 10126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TOUCH_EXPLORATION: 10136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TOUCH_EXPLORE_SECOND_PRESS: 10146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case ONE_FINGER_PASSTHROUGH: 10156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case CORNER_PASSTHROUGH: 10166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case WAIT_FOR_NO_FINGERS: 10176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (gesture_provider_.get()) 10186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_.reset(NULL); 10196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 10206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case NO_FINGERS_DOWN: 10216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gesture_provider_.reset(new GestureProviderAura(this)); 10226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (sound_timer_.IsRunning()) 10236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sound_timer_.Stop(); 10246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tap_timer_.Stop(); 10256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 10266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case SINGLE_TAP_PRESSED: 10276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case GESTURE_IN_PROGRESS: 10286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case SLIDE_GESTURE: 10296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TWO_FINGER_TAP: 10306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 10316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1032f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1033f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void TouchExplorationController::VlogState(const char* function_name) { 1035116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!VLOG_on_) 1036116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 1037f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (prev_state_ == state_) 1038f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 1039f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prev_state_ = state_; 1040f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* state_string = EnumStateToString(state_); 1041f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VLOG(0) << "\n Function name: " << function_name 1042f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << "\n State: " << state_string; 1043f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1044f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1045f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void TouchExplorationController::VlogEvent(const ui::TouchEvent& touch_event, 1046f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* function_name) { 1047116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!VLOG_on_) 1048116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 1049116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1050116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (prev_event_ != NULL && 1051116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prev_event_->type() == touch_event.type() && 1052116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prev_event_->touch_id() == touch_event.touch_id()){ 1053116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 1054f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1055116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The above statement prevents events of the same type and id from being 1056116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // printed in a row. However, if two fingers are down, they would both be 1057116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // moving and alternating printing move events unless we check for this. 1058116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (prev_event_ != NULL && 1059116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prev_event_->type() == ET_TOUCH_MOVED && 1060116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch touch_event.type() == ET_TOUCH_MOVED){ 1061116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 1062116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 10636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1064116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& type = touch_event.name(); 1065116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::PointF& location = touch_event.location_f(); 1066116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int touch_id = touch_event.touch_id(); 1067116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1068116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(0) << "\n Function name: " << function_name 1069116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "\n Event Type: " << type 1070116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "\n Location: " << location.ToString() 1071116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "\n Touch ID: " << touch_id; 1072116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prev_event_.reset(new TouchEvent(touch_event)); 1073f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1074f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1075f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char* TouchExplorationController::EnumStateToString(State state) { 1076f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (state) { 1077f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case NO_FINGERS_DOWN: 1078f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "NO_FINGERS_DOWN"; 1079f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case SINGLE_TAP_PRESSED: 1080f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "SINGLE_TAP_PRESSED"; 1081f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case SINGLE_TAP_RELEASED: 1082f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "SINGLE_TAP_RELEASED"; 1083116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case TOUCH_EXPLORE_RELEASED: 1084116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return "TOUCH_EXPLORE_RELEASED"; 10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case DOUBLE_TAP_PENDING: 10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "DOUBLE_TAP_PENDING"; 10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case TOUCH_RELEASE_PENDING: 10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "TOUCH_RELEASE_PENDING"; 1089f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case TOUCH_EXPLORATION: 1090f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "TOUCH_EXPLORATION"; 1091116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case GESTURE_IN_PROGRESS: 1092116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return "GESTURE_IN_PROGRESS"; 1093f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case TOUCH_EXPLORE_SECOND_PRESS: 1094f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "TOUCH_EXPLORE_SECOND_PRESS"; 10956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case CORNER_PASSTHROUGH: 10966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return "CORNER_PASSTHROUGH"; 10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case SLIDE_GESTURE: 10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "SLIDE_GESTURE"; 10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case ONE_FINGER_PASSTHROUGH: 11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return "ONE_FINGER_PASSTHROUGH"; 11016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case WAIT_FOR_NO_FINGERS: 11026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return "WAIT_FOR_NO_FINGERS"; 11036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case TWO_FINGER_TAP: 11046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return "TWO_FINGER_TAP"; 1105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return "Not a state"; 1107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 11096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// TODO(evy, lisayin) : Just call abstracted methods on the delegate (e.g. 11106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Swipe(Direction direction, int num_fingers)), and add the DispatchXYZ 11116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// methods to the delegate. Avoid the middle step of dispatching keys at all, 11126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// and simply have ChromeVox/ChromeOS complete the required action. 11136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void TouchExplorationController::InitializeSwipeGestureMaps() { 11156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gestures with one finger are used for navigation. 11166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_LEFT); 11176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_RIGHT); 11186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) up_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_UP); 11196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) down_swipe_gestures_[1] = BindShiftSearchKeyEvent(ui::VKEY_DOWN); 11206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gestures with two fingers. 11226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_swipe_gestures_[2] = 11236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(ui::VKEY_BROWSER_BACK, ui::EF_NONE); 11246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_swipe_gestures_[2] = 11256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(ui::VKEY_BROWSER_FORWARD, ui::EF_NONE); 11266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Jump to top. 11276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) up_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_A); 11286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Read from here. 11296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) down_swipe_gestures_[2] = BindShiftSearchKeyEvent(ui::VKEY_R); 11306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gestures with three fingers switch tabs left/right and scroll up/down. 11326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_swipe_gestures_[3] = BindKeyEventWithFlags( 11336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::VKEY_TAB, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); 11346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_swipe_gestures_[3] = 11356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(ui::VKEY_TAB, ui::EF_CONTROL_DOWN); 11366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) up_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_NEXT, ui::EF_NONE); 11376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) down_swipe_gestures_[3] = BindKeyEventWithFlags(ui::VKEY_PRIOR, ui::EF_NONE); 11386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gestures with four fingers should probably eventually be used for rare 11406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // needs that are hard to access through menus. 11416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Note that brightness levels are here because they can be important for low 11426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // vision users. However, none of these mappings are permanent. 11436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_swipe_gestures_[4] = 11446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); 11456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_swipe_gestures_[4] = 11466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(VKEY_BRIGHTNESS_UP, ui::EF_NONE); 11476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) up_swipe_gestures_[4] = BindKeyEventWithFlags(VKEY_BROWSER_HOME, ui::EF_NONE); 11486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) down_swipe_gestures_[4] = 11496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BindKeyEventWithFlags(VKEY_BROWSER_REFRESH, ui::EF_NONE); 11506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 11516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const float TouchExplorationController::GetSplitTapTouchSlop() { 11536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return gesture_detector_config_.touch_slop * 3; 11546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 11556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace ui 1157