1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ash/wm/gestures/overview_gesture_handler.h" 6 7 #include "ash/metrics/user_metrics_recorder.h" 8 #include "ash/shell.h" 9 #include "ash/wm/overview/window_selector_controller.h" 10 #include "ui/aura/window.h" 11 #include "ui/events/event.h" 12 #include "ui/events/event_constants.h" 13 #include "ui/gfx/rect.h" 14 #include "ui/gfx/screen.h" 15 #include "ui/wm/core/coordinate_conversion.h" 16 17 namespace ash { 18 namespace { 19 20 // The number of pixels from the top of the screen (a virtual bezel) to allow 21 // the overview swipe down gesture to begin within. Note this does not actually 22 // prevent handling of the touches so a fullscreen page which consumes these can 23 // prevent entering overview with a swipe down. 24 const int kTopBezelExtraPixels = 5; 25 26 // The threshold before engaging overview on a three finger swipe on the 27 // touchpad. 28 const float kSwipeThresholdPixels = 300; 29 30 } // namespace; 31 32 OverviewGestureHandler::OverviewGestureHandler() 33 : in_top_bezel_gesture_(false), 34 scroll_x_(0), 35 scroll_y_(0) { 36 } 37 38 OverviewGestureHandler::~OverviewGestureHandler() { 39 } 40 41 bool OverviewGestureHandler::ProcessScrollEvent(const ui::ScrollEvent& event) { 42 if (event.type() == ui::ET_SCROLL_FLING_START || 43 event.type() == ui::ET_SCROLL_FLING_CANCEL || 44 event.finger_count() != 3) { 45 scroll_x_ = scroll_y_ = 0; 46 return false; 47 } 48 49 scroll_x_ += event.x_offset(); 50 scroll_y_ += event.y_offset(); 51 52 // Horizontal swiping is ignored. 53 if (std::fabs(scroll_x_) >= std::fabs(scroll_y_)) { 54 scroll_x_ = scroll_y_ = 0; 55 return false; 56 } 57 58 // Only allow swipe up to enter overview, down to exit. Ignore extra swiping 59 // in the wrong direction. 60 Shell* shell = Shell::GetInstance(); 61 if (shell->window_selector_controller()->IsSelecting()) { 62 if (scroll_y_ < 0) 63 scroll_x_ = scroll_y_ = 0; 64 if (scroll_y_ < kSwipeThresholdPixels) 65 return false; 66 } else { 67 if (scroll_y_ > 0) 68 scroll_x_ = scroll_y_ = 0; 69 if (scroll_y_ > -kSwipeThresholdPixels) 70 return false; 71 } 72 73 // Reset scroll amount on toggling. 74 scroll_x_ = scroll_y_ = 0; 75 shell->metrics()->RecordUserMetricsAction(UMA_TOUCHPAD_GESTURE_OVERVIEW); 76 shell->window_selector_controller()->ToggleOverview(); 77 return true; 78 } 79 80 bool OverviewGestureHandler::ProcessGestureEvent( 81 const ui::GestureEvent& event) { 82 // Detect at the beginning of any gesture whether it begins on the top bezel. 83 if (event.type() == ui::ET_GESTURE_BEGIN && 84 event.details().touch_points() == 1) { 85 gfx::Point point_in_screen(event.location()); 86 aura::Window* target = static_cast<aura::Window*>(event.target()); 87 ::wm::ConvertPointToScreen(target, &point_in_screen); 88 in_top_bezel_gesture_ = !Shell::GetScreen()->GetDisplayNearestPoint( 89 point_in_screen).bounds().y() + kTopBezelExtraPixels > 90 point_in_screen.y(); 91 return false; 92 } 93 94 if (!in_top_bezel_gesture_ || 95 event.type() != ui::ET_GESTURE_SWIPE || 96 !event.details().swipe_down() || 97 event.details().touch_points() != 3) { 98 return false; 99 } 100 101 Shell* shell = Shell::GetInstance(); 102 shell->metrics()->RecordUserMetricsAction(UMA_GESTURE_OVERVIEW); 103 shell->window_selector_controller()->ToggleOverview(); 104 return true; 105 } 106 107 } // namespace ash 108