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 "chrome/browser/ui/app_list/app_list_positioner.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10namespace {
11
12const int kScreenWidth = 800;
13const int kScreenHeight = 600;
14
15const int kWindowWidth = 100;
16const int kWindowHeight = 200;
17
18// Size of the menu bar along the top of the screen.
19const int kMenuBarSize = 22;
20// Size of the normal (non-hidden) shelf.
21const int kShelfSize = 30;
22
23// The distance the shelf will appear from the edge of the screen.
24const int kMinDistanceFromEdge = 3;
25
26// A cursor position that is within the shelf. This must be < kShelfSize.
27const int kCursorOnShelf = kShelfSize / 2;
28// A cursor position that should be ignored.
29const int kCursorIgnore = -300;
30
31// A position for the center of the window that causes the window to overlap the
32// edge of the screen. This must be < kWindowWidth / 2 and < kWindowHeight / 2.
33const int kWindowNearEdge = kWindowWidth / 4;
34// A position for the center of the window that places the window away from all
35// edges of the screen. This must be > kWindowWidth / 2, > kWindowHeight / 2, <
36// kScreenWidth - kWindowWidth / 2 and < kScreenHeight - kWindowHeight / 2.
37const int kWindowAwayFromEdge = 158;
38
39}  // namespace
40
41class AppListPositionerUnitTest : public testing::Test {
42 public:
43  void ResetPositioner() {
44    gfx::Size view_size(kWindowWidth, kWindowHeight);
45    positioner_.reset(
46        new AppListPositioner(display_, view_size, kMinDistanceFromEdge));
47  }
48
49  virtual void SetUp() OVERRIDE {
50    display_.set_bounds(gfx::Rect(0, 0, kScreenWidth, kScreenHeight));
51    // Assume there is a menu bar at the top of the screen, as on Mac and Unity.
52    // This is for cases where the work area does not fill the entire screen.
53    display_.set_work_area(
54        gfx::Rect(0, kMenuBarSize, kScreenWidth, kScreenHeight - kMenuBarSize));
55    ResetPositioner();
56    cursor_ = gfx::Point();
57  }
58
59  // Sets up the test environment with the shelf along a given edge of the work
60  // area.
61  void PlaceShelf(AppListPositioner::ScreenEdge edge) {
62    ResetPositioner();
63    switch (edge) {
64      case AppListPositioner::SCREEN_EDGE_UNKNOWN:
65        break;
66      case AppListPositioner::SCREEN_EDGE_LEFT:
67        positioner_->WorkAreaInset(kShelfSize, 0, 0, 0);
68        break;
69      case AppListPositioner::SCREEN_EDGE_RIGHT:
70        positioner_->WorkAreaInset(0, 0, kShelfSize, 0);
71        break;
72      case AppListPositioner::SCREEN_EDGE_TOP:
73        positioner_->WorkAreaInset(0, kShelfSize, 0, 0);
74        break;
75      case AppListPositioner::SCREEN_EDGE_BOTTOM:
76        positioner_->WorkAreaInset(0, 0, 0, kShelfSize);
77        break;
78    }
79  }
80
81  // Set up the test mouse cursor in a given location.
82  void PlaceCursor(int x, int y) {
83    cursor_ = gfx::Point(x, y);
84  }
85
86  gfx::Point DoGetAnchorPointForScreenCorner(
87      AppListPositioner::ScreenCorner corner) const {
88    return positioner_->GetAnchorPointForScreenCorner(corner);
89  }
90
91  gfx::Point DoGetAnchorPointForShelfCorner(
92      AppListPositioner::ScreenEdge shelf_edge) const {
93    return positioner_->GetAnchorPointForShelfCorner(shelf_edge);
94  }
95
96  gfx::Point DoGetAnchorPointForShelfCenter(
97      AppListPositioner::ScreenEdge shelf_edge) const {
98    return positioner_->GetAnchorPointForShelfCenter(shelf_edge);
99  }
100
101  gfx::Point DoGetAnchorPointForShelfCursor(
102      AppListPositioner::ScreenEdge shelf_edge) const {
103    return positioner_->GetAnchorPointForShelfCursor(shelf_edge, cursor_);
104  }
105
106  AppListPositioner::ScreenEdge DoGetShelfEdge(
107      const gfx::Rect& shelf_rect) const {
108    return positioner_->GetShelfEdge(shelf_rect);
109  }
110
111  int DoGetCursorDistanceFromShelf(
112      AppListPositioner::ScreenEdge shelf_edge) const {
113    return positioner_->GetCursorDistanceFromShelf(shelf_edge, cursor_);
114  }
115
116 private:
117  gfx::Display display_;
118  scoped_ptr<AppListPositioner> positioner_;
119  gfx::Point cursor_;
120};
121
122TEST_F(AppListPositionerUnitTest, ScreenCorner) {
123  // Position the app list in a corner of the screen.
124  // Top-left corner.
125  EXPECT_EQ(gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
126                       kMenuBarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
127            DoGetAnchorPointForScreenCorner(
128                AppListPositioner::SCREEN_CORNER_TOP_LEFT));
129
130  // Top-right corner.
131  EXPECT_EQ(gfx::Point(kScreenWidth - kWindowWidth / 2 - kMinDistanceFromEdge,
132                       kMenuBarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
133            DoGetAnchorPointForScreenCorner(
134                AppListPositioner::SCREEN_CORNER_TOP_RIGHT));
135
136  // Bottom-left corner.
137  EXPECT_EQ(
138      gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
139                 kScreenHeight - kWindowHeight / 2 - kMinDistanceFromEdge),
140      DoGetAnchorPointForScreenCorner(
141          AppListPositioner::SCREEN_CORNER_BOTTOM_LEFT));
142
143  // Bottom-right corner.
144  EXPECT_EQ(
145      gfx::Point(kScreenWidth - kWindowWidth / 2 - kMinDistanceFromEdge,
146                 kScreenHeight - kWindowHeight / 2 - kMinDistanceFromEdge),
147      DoGetAnchorPointForScreenCorner(
148          AppListPositioner::SCREEN_CORNER_BOTTOM_RIGHT));
149}
150
151TEST_F(AppListPositionerUnitTest, ShelfCorner) {
152  // Position the app list on the shelf, aligned with the top or left corner.
153  // Shelf on left. Expect app list in top-left corner.
154  PlaceShelf(AppListPositioner::SCREEN_EDGE_LEFT);
155  EXPECT_EQ(
156      gfx::Point(kShelfSize + kWindowWidth / 2 + kMinDistanceFromEdge,
157                 kMenuBarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
158      DoGetAnchorPointForShelfCorner(AppListPositioner::SCREEN_EDGE_LEFT));
159
160  // Shelf on right. Expect app list in top-right corner.
161  PlaceShelf(AppListPositioner::SCREEN_EDGE_RIGHT);
162  EXPECT_EQ(
163      gfx::Point(
164          kScreenWidth - kShelfSize - kWindowWidth / 2 - kMinDistanceFromEdge,
165          kMenuBarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
166      DoGetAnchorPointForShelfCorner(AppListPositioner::SCREEN_EDGE_RIGHT));
167
168  // Shelf on top. Expect app list in top-left corner.
169  PlaceShelf(AppListPositioner::SCREEN_EDGE_TOP);
170  EXPECT_EQ(gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
171                       kMenuBarSize + kShelfSize + kWindowHeight / 2 +
172                           kMinDistanceFromEdge),
173            DoGetAnchorPointForShelfCorner(AppListPositioner::SCREEN_EDGE_TOP));
174
175  // Shelf on bottom. Expect app list in bottom-left corner.
176  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
177  EXPECT_EQ(
178      gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
179                 kScreenHeight - kShelfSize - kWindowHeight / 2 -
180                     kMinDistanceFromEdge),
181      DoGetAnchorPointForShelfCorner(AppListPositioner::SCREEN_EDGE_BOTTOM));
182}
183
184TEST_F(AppListPositionerUnitTest, ShelfCenter) {
185  // Position the app list on the shelf, aligned with the shelf center.
186  PlaceShelf(AppListPositioner::SCREEN_EDGE_LEFT);
187  // Shelf on left. Expect app list to be center-left.
188  EXPECT_EQ(
189      gfx::Point(kShelfSize + kWindowWidth / 2 + kMinDistanceFromEdge,
190                 (kMenuBarSize + kScreenHeight) / 2),
191      DoGetAnchorPointForShelfCenter(AppListPositioner::SCREEN_EDGE_LEFT));
192
193  // Shelf on right. Expect app list to be center-right.
194  PlaceShelf(AppListPositioner::SCREEN_EDGE_RIGHT);
195  EXPECT_EQ(
196      gfx::Point(
197          kScreenWidth - kShelfSize - kWindowWidth / 2 - kMinDistanceFromEdge,
198          (kMenuBarSize + kScreenHeight) / 2),
199      DoGetAnchorPointForShelfCenter(AppListPositioner::SCREEN_EDGE_RIGHT));
200
201  // Shelf on top. Expect app list to be top-center.
202  PlaceShelf(AppListPositioner::SCREEN_EDGE_TOP);
203  EXPECT_EQ(gfx::Point(kScreenWidth / 2,
204                       kMenuBarSize + kShelfSize + kWindowHeight / 2 +
205                           kMinDistanceFromEdge),
206            DoGetAnchorPointForShelfCenter(AppListPositioner::SCREEN_EDGE_TOP));
207
208  // Shelf on bottom. Expect app list to be bottom-center.
209  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
210  EXPECT_EQ(
211      gfx::Point(kScreenWidth / 2,
212                 kScreenHeight - kShelfSize - kWindowHeight / 2 -
213                     kMinDistanceFromEdge),
214      DoGetAnchorPointForShelfCenter(AppListPositioner::SCREEN_EDGE_BOTTOM));
215}
216
217TEST_F(AppListPositionerUnitTest, ShelfCursor) {
218  // Position the app list on the shelf, aligned with the mouse cursor.
219
220  // Shelf on left. Expect app list in top-left corner.
221  PlaceShelf(AppListPositioner::SCREEN_EDGE_LEFT);
222  PlaceCursor(kCursorIgnore, kWindowAwayFromEdge);
223  EXPECT_EQ(
224      gfx::Point(kShelfSize + kWindowWidth / 2 + kMinDistanceFromEdge,
225                 kWindowAwayFromEdge),
226      DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_LEFT));
227
228  // Shelf on right. Expect app list in top-right corner.
229  PlaceShelf(AppListPositioner::SCREEN_EDGE_RIGHT);
230  PlaceCursor(kCursorIgnore, kWindowAwayFromEdge);
231  EXPECT_EQ(
232      gfx::Point(
233          kScreenWidth - kShelfSize - kWindowWidth / 2 - kMinDistanceFromEdge,
234          kWindowAwayFromEdge),
235      DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_RIGHT));
236
237  // Shelf on top. Expect app list in top-left corner.
238  PlaceShelf(AppListPositioner::SCREEN_EDGE_TOP);
239  PlaceCursor(kWindowAwayFromEdge, kCursorIgnore);
240  EXPECT_EQ(gfx::Point(kWindowAwayFromEdge,
241                       kMenuBarSize + kShelfSize + kWindowHeight / 2 +
242                           kMinDistanceFromEdge),
243            DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_TOP));
244
245  // Shelf on bottom. Expect app list in bottom-left corner.
246  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
247  PlaceCursor(kWindowAwayFromEdge, kCursorIgnore);
248  EXPECT_EQ(
249      gfx::Point(kWindowAwayFromEdge,
250                 kScreenHeight - kShelfSize - kWindowHeight / 2 -
251                     kMinDistanceFromEdge),
252      DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_BOTTOM));
253
254  // Shelf on bottom. Mouse near left edge. App list must not go off screen.
255  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
256  PlaceCursor(kWindowNearEdge, kCursorIgnore);
257  EXPECT_EQ(
258      gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
259                 kScreenHeight - kShelfSize - kWindowHeight / 2 -
260                     kMinDistanceFromEdge),
261      DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_BOTTOM));
262
263  // Shelf on bottom. Mouse near right edge. App list must not go off screen.
264  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
265  PlaceCursor(kScreenWidth - kWindowNearEdge, kCursorIgnore);
266  EXPECT_EQ(
267      gfx::Point(kScreenWidth - kWindowWidth / 2 - kMinDistanceFromEdge,
268                 kScreenHeight - kShelfSize - kWindowHeight / 2 -
269                     kMinDistanceFromEdge),
270      DoGetAnchorPointForShelfCursor(AppListPositioner::SCREEN_EDGE_BOTTOM));
271}
272
273TEST_F(AppListPositionerUnitTest, GetShelfEdge) {
274  gfx::Rect shelf_rect;
275  // Shelf on left.
276  shelf_rect =
277      gfx::Rect(0, kMenuBarSize, kShelfSize, kScreenHeight - kMenuBarSize);
278  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_LEFT, DoGetShelfEdge(shelf_rect));
279
280  // Shelf on right.
281  shelf_rect = gfx::Rect(kScreenWidth - kShelfSize,
282                         kMenuBarSize,
283                         kShelfSize,
284                         kScreenHeight - kMenuBarSize);
285  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_RIGHT, DoGetShelfEdge(shelf_rect));
286
287  // Shelf on top.
288  shelf_rect = gfx::Rect(0, 0, kScreenWidth, kShelfSize);
289  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_TOP, DoGetShelfEdge(shelf_rect));
290
291  // Shelf on bottom.
292  shelf_rect =
293      gfx::Rect(0, kScreenHeight - kShelfSize, kScreenWidth, kShelfSize);
294  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_BOTTOM, DoGetShelfEdge(shelf_rect));
295
296  // A couple of inconclusive cases, which should return unknown.
297  shelf_rect = gfx::Rect();
298  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_UNKNOWN, DoGetShelfEdge(shelf_rect));
299  shelf_rect = gfx::Rect(-10, 0, kScreenWidth, kShelfSize);
300  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_UNKNOWN, DoGetShelfEdge(shelf_rect));
301  shelf_rect = gfx::Rect(10, 0, kScreenWidth - 20, kShelfSize);
302  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_UNKNOWN, DoGetShelfEdge(shelf_rect));
303  shelf_rect = gfx::Rect(0, kShelfSize, kScreenWidth, 60);
304  EXPECT_EQ(AppListPositioner::SCREEN_EDGE_UNKNOWN, DoGetShelfEdge(shelf_rect));
305}
306
307TEST_F(AppListPositionerUnitTest, GetCursorDistanceFromShelf) {
308  // Shelf on left.
309  PlaceShelf(AppListPositioner::SCREEN_EDGE_LEFT);
310  PlaceCursor(kWindowAwayFromEdge, kCursorIgnore);
311  EXPECT_EQ(kWindowAwayFromEdge - kShelfSize,
312            DoGetCursorDistanceFromShelf(AppListPositioner::SCREEN_EDGE_LEFT));
313
314  // Shelf on right.
315  PlaceShelf(AppListPositioner::SCREEN_EDGE_RIGHT);
316  PlaceCursor(kScreenWidth - kWindowAwayFromEdge, kCursorIgnore);
317  EXPECT_EQ(kWindowAwayFromEdge - kShelfSize,
318            DoGetCursorDistanceFromShelf(AppListPositioner::SCREEN_EDGE_RIGHT));
319
320  // Shelf on top.
321  PlaceShelf(AppListPositioner::SCREEN_EDGE_TOP);
322  PlaceCursor(kCursorIgnore, kMenuBarSize + kWindowAwayFromEdge);
323  EXPECT_EQ(kWindowAwayFromEdge - kShelfSize,
324            DoGetCursorDistanceFromShelf(AppListPositioner::SCREEN_EDGE_TOP));
325
326  // Shelf on bottom.
327  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
328  PlaceCursor(kCursorIgnore, kScreenHeight - kWindowAwayFromEdge);
329  EXPECT_EQ(
330      kWindowAwayFromEdge - kShelfSize,
331      DoGetCursorDistanceFromShelf(AppListPositioner::SCREEN_EDGE_BOTTOM));
332
333  // Shelf on bottom. Cursor inside shelf; expect 0.
334  PlaceShelf(AppListPositioner::SCREEN_EDGE_BOTTOM);
335  PlaceCursor(kCursorIgnore, kScreenHeight - kCursorOnShelf);
336  EXPECT_EQ(
337      0, DoGetCursorDistanceFromShelf(AppListPositioner::SCREEN_EDGE_BOTTOM));
338}
339