1// Copyright 2014 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/system/web_notification/ash_popup_alignment_delegate.h"
6
7#include <vector>
8
9#include "ash/shelf/shelf_layout_manager.h"
10#include "ash/shelf/shelf_types.h"
11#include "ash/shell.h"
12#include "ash/shell_window_ids.h"
13#include "ash/test/ash_test_base.h"
14#include "ui/gfx/screen.h"
15#include "ui/message_center/message_center_style.h"
16
17namespace ash {
18
19class AshPopupAlignmentDelegateTest : public test::AshTestBase {
20 public:
21  AshPopupAlignmentDelegateTest() {}
22  virtual ~AshPopupAlignmentDelegateTest() {}
23
24  virtual void SetUp() {
25    test::AshTestBase::SetUp();
26    alignment_delegate_.reset(new AshPopupAlignmentDelegate());
27    alignment_delegate_->StartObserving(
28        Shell::GetScreen(), Shell::GetScreen()->GetPrimaryDisplay());
29  }
30
31  virtual void TearDown() {
32    alignment_delegate_.reset();
33    test::AshTestBase::TearDown();
34  }
35
36 protected:
37  enum Position {
38    TOP_LEFT,
39    TOP_RIGHT,
40    BOTTOM_LEFT,
41    BOTTOM_RIGHT,
42    OUTSIDE
43  };
44
45  AshPopupAlignmentDelegate* alignment_delegate() {
46    return alignment_delegate_.get();
47  }
48
49  Position GetPositionInDisplay(const gfx::Point& point) {
50    const gfx::Rect& work_area =
51        Shell::GetScreen()->GetPrimaryDisplay().work_area();
52    const gfx::Point center_point = work_area.CenterPoint();
53    if (work_area.x() > point.x() || work_area.y() > point.y() ||
54        work_area.right() < point.x() || work_area.bottom() < point.y()) {
55      return OUTSIDE;
56    }
57
58    if (center_point.x() < point.x())
59      return (center_point.y() < point.y()) ? BOTTOM_RIGHT : TOP_RIGHT;
60    else
61      return (center_point.y() < point.y()) ? BOTTOM_LEFT : TOP_LEFT;
62  }
63
64  gfx::Rect GetWorkArea() {
65    return alignment_delegate_->work_area_;
66  }
67
68 private:
69  scoped_ptr<AshPopupAlignmentDelegate> alignment_delegate_;
70};
71
72TEST_F(AshPopupAlignmentDelegateTest, ShelfAlignment) {
73  const gfx::Rect toast_size(0, 0, 10, 10);
74  UpdateDisplay("600x600");
75  gfx::Point toast_point;
76  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
77  toast_point.set_y(alignment_delegate()->GetBaseLine());
78  EXPECT_EQ(BOTTOM_RIGHT, GetPositionInDisplay(toast_point));
79  EXPECT_FALSE(alignment_delegate()->IsTopDown());
80  EXPECT_FALSE(alignment_delegate()->IsFromLeft());
81
82  Shell::GetInstance()->SetShelfAlignment(
83      SHELF_ALIGNMENT_RIGHT,
84      Shell::GetPrimaryRootWindow());
85  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
86  toast_point.set_y(alignment_delegate()->GetBaseLine());
87  EXPECT_EQ(BOTTOM_RIGHT, GetPositionInDisplay(toast_point));
88  EXPECT_FALSE(alignment_delegate()->IsTopDown());
89  EXPECT_FALSE(alignment_delegate()->IsFromLeft());
90
91  Shell::GetInstance()->SetShelfAlignment(
92      SHELF_ALIGNMENT_LEFT,
93      Shell::GetPrimaryRootWindow());
94  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
95  toast_point.set_y(alignment_delegate()->GetBaseLine());
96  EXPECT_EQ(BOTTOM_LEFT, GetPositionInDisplay(toast_point));
97  EXPECT_FALSE(alignment_delegate()->IsTopDown());
98  EXPECT_TRUE(alignment_delegate()->IsFromLeft());
99
100  Shell::GetInstance()->SetShelfAlignment(
101      SHELF_ALIGNMENT_TOP,
102      Shell::GetPrimaryRootWindow());
103  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
104  toast_point.set_y(alignment_delegate()->GetBaseLine());
105  EXPECT_EQ(TOP_RIGHT, GetPositionInDisplay(toast_point));
106  EXPECT_TRUE(alignment_delegate()->IsTopDown());
107  EXPECT_FALSE(alignment_delegate()->IsFromLeft());
108}
109
110TEST_F(AshPopupAlignmentDelegateTest, LockScreen) {
111  const gfx::Rect toast_size(0, 0, 10, 10);
112
113  Shell::GetInstance()->SetShelfAlignment(
114      SHELF_ALIGNMENT_LEFT,
115      Shell::GetPrimaryRootWindow());
116  gfx::Point toast_point;
117  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
118  toast_point.set_y(alignment_delegate()->GetBaseLine());
119  EXPECT_EQ(BOTTOM_LEFT, GetPositionInDisplay(toast_point));
120  EXPECT_FALSE(alignment_delegate()->IsTopDown());
121  EXPECT_TRUE(alignment_delegate()->IsFromLeft());
122
123  BlockUserSession(BLOCKED_BY_LOCK_SCREEN);
124  toast_point.set_x(alignment_delegate()->GetToastOriginX(toast_size));
125  toast_point.set_y(alignment_delegate()->GetBaseLine());
126  EXPECT_EQ(BOTTOM_RIGHT, GetPositionInDisplay(toast_point));
127  EXPECT_FALSE(alignment_delegate()->IsTopDown());
128  EXPECT_FALSE(alignment_delegate()->IsFromLeft());
129}
130
131TEST_F(AshPopupAlignmentDelegateTest, AutoHide) {
132  const gfx::Rect toast_size(0, 0, 10, 10);
133  UpdateDisplay("600x600");
134  int origin_x = alignment_delegate()->GetToastOriginX(toast_size);
135  int baseline = alignment_delegate()->GetBaseLine();
136
137  // Create a window, otherwise autohide doesn't work.
138  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
139  Shell::GetInstance()->SetShelfAutoHideBehavior(
140      SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS,
141      Shell::GetPrimaryRootWindow());
142  ShelfLayoutManager::ForShelf(Shell::GetPrimaryRootWindow())->
143      UpdateAutoHideStateNow();
144  EXPECT_EQ(origin_x, alignment_delegate()->GetToastOriginX(toast_size));
145  EXPECT_LT(baseline, alignment_delegate()->GetBaseLine());
146}
147
148// Verify that docked window doesn't affect the popup alignment.
149TEST_F(AshPopupAlignmentDelegateTest, DockedWindow) {
150  const gfx::Rect toast_size(0, 0, 10, 10);
151  UpdateDisplay("600x600");
152  int origin_x = alignment_delegate()->GetToastOriginX(toast_size);
153  int baseline = alignment_delegate()->GetBaseLine();
154
155  scoped_ptr<aura::Window> window(
156      CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 50, 50)));
157  aura::Window* docked_container = Shell::GetContainer(
158      Shell::GetPrimaryRootWindow(),
159      kShellWindowId_DockedContainer);
160  docked_container->AddChild(window.get());
161
162  EXPECT_EQ(origin_x, alignment_delegate()->GetToastOriginX(toast_size));
163  EXPECT_EQ(baseline, alignment_delegate()->GetBaseLine());
164  EXPECT_FALSE(alignment_delegate()->IsTopDown());
165  EXPECT_FALSE(alignment_delegate()->IsFromLeft());
166}
167
168TEST_F(AshPopupAlignmentDelegateTest, DisplayResize) {
169  const gfx::Rect toast_size(0, 0, 10, 10);
170  UpdateDisplay("600x600");
171  int origin_x = alignment_delegate()->GetToastOriginX(toast_size);
172  int baseline = alignment_delegate()->GetBaseLine();
173
174  UpdateDisplay("800x800");
175  EXPECT_LT(origin_x, alignment_delegate()->GetToastOriginX(toast_size));
176  EXPECT_LT(baseline, alignment_delegate()->GetBaseLine());
177
178  UpdateDisplay("400x400");
179  EXPECT_GT(origin_x, alignment_delegate()->GetToastOriginX(toast_size));
180  EXPECT_GT(baseline, alignment_delegate()->GetBaseLine());
181}
182
183TEST_F(AshPopupAlignmentDelegateTest, TrayHeight) {
184  const gfx::Rect toast_size(0, 0, 10, 10);
185  UpdateDisplay("600x600");
186  int origin_x = alignment_delegate()->GetToastOriginX(toast_size);
187  int baseline = alignment_delegate()->GetBaseLine();
188
189  const int kTrayHeight = 100;
190  alignment_delegate()->SetSystemTrayHeight(kTrayHeight);
191
192  EXPECT_EQ(origin_x, alignment_delegate()->GetToastOriginX(toast_size));
193  EXPECT_EQ(baseline - kTrayHeight - message_center::kMarginBetweenItems,
194            alignment_delegate()->GetBaseLine());
195}
196
197}  // namespace ash
198