1 // Copyright (c) 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.
5 #include "ash/wm/gestures/edge_gesture_handler.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf_layout_manager.h"
9 #include "ash/shelf/shelf_types.h"
10 #include "ash/shelf/shelf_widget.h"
11 #include "ash/shell.h"
12 #include "ui/base/events/event.h"
13 #include "ui/gfx/screen.h"
16 const int kBottomEdgeGestureThreshold
= 10;
17 const int kLeftEdgeGestureThreshold
= 10;
18 const int kRightEdgeGestureThreshold
= 10;
19 const int kTopEdgeGestureThreshold
= 10;
21 // Bit positions of edge start flags
29 // Helpers for manipulating edge start flags
30 #define CLEAR_FLAGS(FLAGS) (FLAGS = 0)
31 #define SET_FLAG(FLAGS, FLAG_POS) (FLAGS |= 1 << FLAG_POS)
32 #define IS_FLAG_SET(FLAGS, FLAG_POS) (0 != (FLAGS & (1 << FLAG_POS)))
33 #define ANY_FLAGS_SET(FLAGS) (FLAGS != 0)
39 EdgeGestureHandler::EdgeGestureHandler() :
40 orientation_(EDGE_SCROLL_ORIENTATION_UNSET
) {
41 CLEAR_FLAGS(start_location_
);
44 EdgeGestureHandler::~EdgeGestureHandler() {
47 bool EdgeGestureHandler::ProcessGestureEvent(aura::Window
* target
,
48 const ui::GestureEvent
& event
) {
49 // TODO(crbug.com/222746): Rewrite this code to ignore events that are for
50 // edges that a bezel is present for instead of hardcoding the layout of edge
52 switch (event
.type()) {
53 case ui::ET_GESTURE_SCROLL_BEGIN
:
54 return HandleEdgeGestureStart(target
, event
);
55 case ui::ET_GESTURE_SCROLL_UPDATE
:
56 if (ANY_FLAGS_SET(start_location_
)) {
57 if (DetermineGestureOrientation(event
)) {
58 return HandleEdgeGestureUpdate(target
, event
);
62 case ui::ET_GESTURE_SCROLL_END
:
63 case ui::ET_SCROLL_FLING_START
:
64 return HandleEdgeGestureEnd(target
, event
);
71 bool EdgeGestureHandler::HandleLauncherControl(const ui::GestureEvent
& event
) {
72 ShelfLayoutManager
* shelf
=
73 Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
74 // If visible then let the shelf handle it as a normal widget.
75 if (shelf
->IsVisible())
78 switch (shelf
->GetAlignment()) {
79 case SHELF_ALIGNMENT_LEFT
:
80 if (IS_FLAG_SET(start_location_
, EDGE_START_LEFT
))
81 return shelf_handler_
.ProcessGestureEvent(event
);
83 case SHELF_ALIGNMENT_RIGHT
:
84 if (IS_FLAG_SET(start_location_
, EDGE_START_RIGHT
))
85 return shelf_handler_
.ProcessGestureEvent(event
);
87 // Let the BezelGestureHandler handle gestures on the bottom edge of the
88 // screen and there are no implemented gestures for the top edge at the
90 case SHELF_ALIGNMENT_BOTTOM
:
91 case SHELF_ALIGNMENT_TOP
:
98 bool EdgeGestureHandler::HandleEdgeGestureStart(
100 const ui::GestureEvent
& event
) {
102 Shell::GetScreen()->GetDisplayNearestWindow(target
).bounds();
104 orientation_
= EDGE_SCROLL_ORIENTATION_UNSET
;
105 if (GestureStartInEdgeArea(screen
, event
))
106 return HandleLauncherControl(event
);
110 bool EdgeGestureHandler::DetermineGestureOrientation(
111 const ui::GestureEvent
& event
) {
112 if (orientation_
== EDGE_SCROLL_ORIENTATION_UNSET
) {
113 if (!event
.details().scroll_x() && !event
.details().scroll_y())
115 orientation_
= abs(event
.details().scroll_y()) >
116 abs(event
.details().scroll_x()) ?
117 EDGE_SCROLL_ORIENTATION_VERTICAL
: EDGE_SCROLL_ORIENTATION_HORIZONTAL
;
122 bool EdgeGestureHandler::HandleEdgeGestureUpdate(
123 aura::Window
* target
,
124 const ui::GestureEvent
& event
) {
125 if (IsGestureInLauncherOrientation(event
))
126 return HandleLauncherControl(event
);
130 bool EdgeGestureHandler::HandleEdgeGestureEnd(aura::Window
* target
,
131 const ui::GestureEvent
& event
) {
132 bool ret_val
= HandleLauncherControl(event
);
133 CLEAR_FLAGS(start_location_
);
137 bool EdgeGestureHandler::GestureStartInEdgeArea(
138 const gfx::Rect
& screen
,
139 const ui::GestureEvent
& event
) {
140 CLEAR_FLAGS(start_location_
);
142 if (abs(event
.y() - screen
.y()) < kTopEdgeGestureThreshold
&&
144 SET_FLAG(start_location_
, EDGE_START_TOP
);
145 if (abs(event
.x() - screen
.x()) < kLeftEdgeGestureThreshold
&&
147 SET_FLAG(start_location_
, EDGE_START_LEFT
);
148 if (abs(event
.x() - screen
.right()) < kRightEdgeGestureThreshold
&&
150 SET_FLAG(start_location_
, EDGE_START_RIGHT
);
151 if (abs(event
.y() - screen
.bottom()) < kBottomEdgeGestureThreshold
&&
153 SET_FLAG(start_location_
, EDGE_START_BOTTOM
);
154 return ANY_FLAGS_SET(start_location_
);
157 bool EdgeGestureHandler::IsGestureInLauncherOrientation(
158 const ui::GestureEvent
& event
) {
159 EdgeScrollOrientation new_orientation
= abs(event
.details().scroll_y()) >
160 abs(event
.details().scroll_x()) ?
161 EDGE_SCROLL_ORIENTATION_VERTICAL
: EDGE_SCROLL_ORIENTATION_HORIZONTAL
;
163 if (new_orientation
!= orientation_
)
166 ShelfLayoutManager
* shelf
=
167 Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
168 switch (shelf
->GetAlignment()) {
169 case SHELF_ALIGNMENT_BOTTOM
:
170 if (orientation_
== EDGE_SCROLL_ORIENTATION_VERTICAL
)
173 case SHELF_ALIGNMENT_LEFT
:
174 if (orientation_
== EDGE_SCROLL_ORIENTATION_HORIZONTAL
)
177 case SHELF_ALIGNMENT_RIGHT
:
178 if (orientation_
== EDGE_SCROLL_ORIENTATION_HORIZONTAL
)
181 case SHELF_ALIGNMENT_TOP
:
182 if (orientation_
== EDGE_SCROLL_ORIENTATION_VERTICAL
)
191 } // namespace internal