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/views/app_list/win/app_list_win.h"
6
7#include "chrome/browser/ui/app_list/app_list_positioner.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#include "ui/gfx/display.h"
10#include "ui/gfx/point.h"
11#include "ui/gfx/rect.h"
12#include "ui/gfx/size.h"
13
14namespace {
15
16const int kScreenWidth = 800;
17const int kScreenHeight = 600;
18
19const int kWindowWidth = 100;
20const int kWindowHeight = 200;
21
22// Size of the normal (non-hidden) taskbar.
23const int kTaskbarSize = 30;
24
25// The distance the taskbar will appear from the edge of the screen.
26const int kMinDistanceFromEdge = 3;
27
28// Max distance the mouse can be from taskbar to count as "near" the taskbar.
29const int kSnapDistance = 50;
30// A cursor position that is within the taskbar. This must be < kTaskbarSize.
31const int kCursorOnTaskbar = kTaskbarSize / 2;
32// A cursor position that is within 50 pixels of the taskbar.
33const int kCursorNearTaskbar = kTaskbarSize + kSnapDistance;
34// A cursor position that is more than 50 pixels away from the taskbar.
35const int kCursorAwayFromTaskbar = kCursorNearTaskbar + 1;
36
37// A position for the center of the window that causes the window to overlap the
38// edge of the screen. This must be < kWindowWidth / 2 and < kWindowHeight / 2.
39const int kWindowNearEdge = kWindowWidth / 4;
40// A position for the center of the window that places the window away from all
41// edges of the screen. This must be > kWindowWidth / 2, > kWindowHeight / 2, <
42// kScreenWidth - kWindowWidth / 2 and < kScreenHeight - kWindowHeight / 2.
43const int kWindowAwayFromEdge = 158;
44
45// Horizontal offset of the simulated Windows 8 split point.
46const int kWin8SplitPoint = 200;
47
48}  // namespace
49
50class AppListWinUnitTest : public testing::Test {
51 public:
52  virtual void SetUp() OVERRIDE {
53    display_.set_bounds(gfx::Rect(0, 0, kScreenWidth, kScreenHeight));
54    display_.set_work_area(gfx::Rect(0, 0, kScreenWidth, kScreenHeight));
55    cursor_ = gfx::Point();
56    taskbar_rect_ = gfx::Rect();
57    center_window_ = false;
58  }
59
60  // Set the display work area.
61  void SetWorkArea(int x, int y, int width, int height) {
62    display_.set_work_area(gfx::Rect(x, y, width, height));
63  }
64
65  // Sets up the test environment with the taskbar along a given edge of the
66  // work area.
67  void PlaceTaskbar(AppListPositioner::ScreenEdge edge) {
68    const gfx::Rect& work_area = display_.work_area();
69    switch (edge) {
70      case AppListPositioner::SCREEN_EDGE_UNKNOWN:
71        taskbar_rect_ = gfx::Rect();
72        break;
73      case AppListPositioner::SCREEN_EDGE_LEFT:
74        taskbar_rect_ = gfx::Rect(
75            work_area.x(), work_area.y(), kTaskbarSize, work_area.height());
76        break;
77      case AppListPositioner::SCREEN_EDGE_RIGHT:
78        taskbar_rect_ =
79            gfx::Rect(work_area.x() + work_area.width() - kTaskbarSize,
80                      work_area.y(),
81                      kTaskbarSize,
82                      work_area.height());
83        break;
84      case AppListPositioner::SCREEN_EDGE_TOP:
85        taskbar_rect_ = gfx::Rect(
86            work_area.x(), work_area.y(), work_area.width(), kTaskbarSize);
87        break;
88      case AppListPositioner::SCREEN_EDGE_BOTTOM:
89        taskbar_rect_ =
90            gfx::Rect(work_area.x(),
91                      work_area.y() + work_area.height() - kTaskbarSize,
92                      work_area.width(),
93                      kTaskbarSize);
94        break;
95    }
96  }
97
98  // Set up the test mouse cursor in a given location.
99  void PlaceCursor(int x, int y) {
100    cursor_ = gfx::Point(x, y);
101  }
102
103  void EnableWindowCentering() {
104    center_window_ = true;
105  }
106
107  gfx::Point DoFindAnchorPoint() const {
108    return AppListWin::FindAnchorPoint(gfx::Size(kWindowWidth, kWindowHeight),
109                                       display_,
110                                       cursor_,
111                                       taskbar_rect_,
112                                       center_window_);
113  }
114
115 private:
116  gfx::Display display_;
117  gfx::Point cursor_;
118  gfx::Rect taskbar_rect_;
119  bool center_window_;
120};
121
122TEST_F(AppListWinUnitTest, FindAnchorPointNoTaskbar) {
123  // Position the app list when there is no taskbar on the display.
124  PlaceCursor(0, 0);
125  // Expect the app list to be in the bottom-left corner.
126  EXPECT_EQ(
127      gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
128                 kScreenHeight - kWindowHeight / 2 - kMinDistanceFromEdge),
129      DoFindAnchorPoint());
130}
131
132TEST_F(AppListWinUnitTest, FindAnchorPointMouseOffTaskbar) {
133  // Position the app list when the mouse is away from the taskbar.
134
135  // Bottom taskbar. Expect the app list to be in the bottom-left corner.
136  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
137  PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorAwayFromTaskbar);
138  EXPECT_EQ(gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
139                       kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
140                           kMinDistanceFromEdge),
141            DoFindAnchorPoint());
142
143  // Top taskbar. Expect the app list to be in the top-left corner.
144  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_TOP);
145  PlaceCursor(kWindowAwayFromEdge, kCursorAwayFromTaskbar);
146  EXPECT_EQ(gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
147                       kTaskbarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
148            DoFindAnchorPoint());
149
150  // Left taskbar. Expect the app list to be in the top-left corner.
151  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_LEFT);
152  PlaceCursor(kCursorAwayFromTaskbar, kWindowAwayFromEdge);
153  EXPECT_EQ(gfx::Point(kTaskbarSize + kWindowWidth / 2 + kMinDistanceFromEdge,
154                       kWindowHeight / 2 + kMinDistanceFromEdge),
155            DoFindAnchorPoint());
156
157  // Right taskbar. Expect the app list to be in the top-right corner.
158  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_RIGHT);
159  PlaceCursor(kScreenWidth - kCursorAwayFromTaskbar, kWindowAwayFromEdge);
160  EXPECT_EQ(gfx::Point(kScreenWidth - kTaskbarSize - kWindowWidth / 2 -
161                           kMinDistanceFromEdge,
162                       kWindowHeight / 2 + kMinDistanceFromEdge),
163            DoFindAnchorPoint());
164}
165
166TEST_F(AppListWinUnitTest, FindAnchorPointMouseOnTaskbar) {
167  // Position the app list when the mouse is over the taskbar.
168
169  // Bottom taskbar (mouse well within taskbar). Expect the app list to be at
170  // the bottom centered on the mouse X coordinate.
171  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
172  PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorOnTaskbar);
173  EXPECT_EQ(gfx::Point(kWindowAwayFromEdge,
174                       kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
175                           kMinDistanceFromEdge),
176            DoFindAnchorPoint());
177
178  // Bottom taskbar (outside the taskbar but still close enough).
179  // Expect the app list to be at the bottom centered on the mouse X coordinate.
180  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
181  PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorNearTaskbar);
182  EXPECT_EQ(gfx::Point(kWindowAwayFromEdge,
183                       kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
184                           kMinDistanceFromEdge),
185            DoFindAnchorPoint());
186
187  // Top taskbar. Expect the app list to be at the top centered on the
188  // mouse X coordinate.
189  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_TOP);
190  PlaceCursor(kWindowAwayFromEdge, kCursorNearTaskbar);
191  EXPECT_EQ(gfx::Point(kWindowAwayFromEdge,
192                       kTaskbarSize + kWindowHeight / 2 + kMinDistanceFromEdge),
193            DoFindAnchorPoint());
194
195  // Left taskbar. Expect the app list to be at the left centered on the
196  // mouse Y coordinate.
197  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_LEFT);
198  PlaceCursor(kCursorNearTaskbar, kWindowAwayFromEdge);
199  EXPECT_EQ(gfx::Point(kTaskbarSize + kWindowWidth / 2 + kMinDistanceFromEdge,
200                       kWindowAwayFromEdge),
201            DoFindAnchorPoint());
202
203  // Right taskbar. Expect the app list to be at the right centered on the
204  // mouse Y coordinate.
205  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_RIGHT);
206  PlaceCursor(kScreenWidth - kCursorNearTaskbar, kWindowAwayFromEdge);
207  EXPECT_EQ(gfx::Point(kScreenWidth - kTaskbarSize - kWindowWidth / 2 -
208                           kMinDistanceFromEdge,
209                       kWindowAwayFromEdge),
210            DoFindAnchorPoint());
211
212  // Bottom taskbar. Mouse near left edge. App list must not go off screen.
213  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
214  PlaceCursor(kWindowNearEdge, kScreenHeight - kCursorOnTaskbar);
215  EXPECT_EQ(gfx::Point(kWindowWidth / 2 + kMinDistanceFromEdge,
216                       kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
217                           kMinDistanceFromEdge),
218            DoFindAnchorPoint());
219
220  // Bottom taskbar. Mouse near right edge. App list must not go off screen.
221  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
222  PlaceCursor(kScreenWidth - kWindowNearEdge, kScreenHeight - kCursorOnTaskbar);
223  EXPECT_EQ(gfx::Point(kScreenWidth - kWindowWidth / 2 - kMinDistanceFromEdge,
224                       kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
225                           kMinDistanceFromEdge),
226            DoFindAnchorPoint());
227}
228
229TEST_F(AppListWinUnitTest, FindAnchorPointWin8SplitScreen) {
230  // Make the work area smaller than the screen, as you would get in Windows 8
231  // when there is a split screen and the Desktop is in one side of the screen.
232  SetWorkArea(
233      kWin8SplitPoint, 0, kScreenWidth - kWin8SplitPoint, kScreenHeight);
234
235  // No taskbar. Expect the app list to be in the bottom-left corner of the work
236  // area.
237  EXPECT_EQ(
238      gfx::Point(kWin8SplitPoint + kWindowWidth / 2 + kMinDistanceFromEdge,
239                 kScreenHeight - kWindowHeight / 2 - kMinDistanceFromEdge),
240      DoFindAnchorPoint());
241
242  // Bottom taskbar (mouse off-screen to the left). Expect the app list to be
243  // in the bottom-left corner of the work area.
244  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_BOTTOM);
245  PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorOnTaskbar);
246  EXPECT_EQ(
247      gfx::Point(kWin8SplitPoint + kWindowWidth / 2 + kMinDistanceFromEdge,
248                 kScreenHeight - kTaskbarSize - kWindowHeight / 2 -
249                     kMinDistanceFromEdge),
250      DoFindAnchorPoint());
251}
252
253TEST_F(AppListWinUnitTest, FindAnchorPointCentered) {
254  // Cursor on the top taskbar; enable centered app list mode.
255  PlaceTaskbar(AppListPositioner::SCREEN_EDGE_TOP);
256  PlaceCursor(0, 0);
257  EnableWindowCentering();
258  // Expect the app list to be in the center of the screen (ignore the cursor).
259  EXPECT_EQ(gfx::Point(kScreenWidth / 2, kScreenHeight / 2),
260            DoFindAnchorPoint());
261}
262