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