blob: 0d91372cdbd737d4c2f9ef6319847b353555299e [file] [log] [blame]
msw757a8f02016-08-03 23:59:421// 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/common/shelf/shelf_window_watcher.h"
6
7#include "ash/common/ash_switches.h"
8#include "ash/common/shelf/shelf_item_types.h"
9#include "ash/common/shelf/shelf_model.h"
10#include "ash/common/shell_window_ids.h"
11#include "ash/common/wm/window_resizer.h"
12#include "ash/common/wm/window_state.h"
13#include "ash/common/wm_lookup.h"
14#include "ash/common/wm_shell.h"
15#include "ash/common/wm_window.h"
16#include "ash/test/ash_test_base.h"
17#include "ui/base/hit_test.h"
18#include "ui/views/widget/widget.h"
19
20namespace ash {
21
22class ShelfWindowWatcherTest : public test::AshTestBase {
23 public:
24 ShelfWindowWatcherTest() : model_(nullptr) {}
25 ~ShelfWindowWatcherTest() override {}
26
27 void SetUp() override {
28 test::AshTestBase::SetUp();
29 model_ = WmShell::Get()->shelf_model();
30 }
31
32 void TearDown() override {
33 model_ = nullptr;
34 test::AshTestBase::TearDown();
35 }
36
37 ShelfID CreateShelfItem(WmWindow* window) {
38 ShelfID id = model_->next_id();
39 ShelfItemDetails item_details;
40 item_details.type = TYPE_PLATFORM_APP;
41 window->SetShelfItemDetails(item_details);
42 return id;
43 }
44
45 protected:
46 ShelfModel* model_;
47
48 private:
49 DISALLOW_COPY_AND_ASSIGN(ShelfWindowWatcherTest);
50};
51
52// Ensure shelf items are added and removed as windows are opened and closed.
53TEST_F(ShelfWindowWatcherTest, OpenAndClose) {
54 // ShelfModel only has an APP_LIST item.
55 EXPECT_EQ(1, model_->item_count());
56
57 // Adding windows with ShelfItemDetails properties adds shelf items.
58 std::unique_ptr<views::Widget> widget1 =
59 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
60 CreateShelfItem(WmLookup::Get()->GetWindowForWidget(widget1.get()));
61 EXPECT_EQ(2, model_->item_count());
62 std::unique_ptr<views::Widget> widget2 =
63 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
64 CreateShelfItem(WmLookup::Get()->GetWindowForWidget(widget2.get()));
65 EXPECT_EQ(3, model_->item_count());
66
67 // Each ShelfItem is removed when the associated window is destroyed.
68 widget1.reset();
69 EXPECT_EQ(2, model_->item_count());
70 widget2.reset();
71 EXPECT_EQ(1, model_->item_count());
72}
73
74TEST_F(ShelfWindowWatcherTest, CreateAndRemoveShelfItemDetails) {
75 // ShelfModel only has an APP_LIST item.
76 EXPECT_EQ(1, model_->item_count());
77
78 // Creating windows without ShelfItemDetails does not add items.
79 std::unique_ptr<views::Widget> widget1 =
80 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
81 WmWindow* window1 = WmLookup::Get()->GetWindowForWidget(widget1.get());
82 std::unique_ptr<views::Widget> widget2 =
83 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
84 WmWindow* window2 = WmLookup::Get()->GetWindowForWidget(widget2.get());
85 EXPECT_EQ(1, model_->item_count());
86
87 // Create a ShelfItem for the first window.
88 ShelfID id_w1 = CreateShelfItem(window1);
89 EXPECT_EQ(2, model_->item_count());
90
91 int index_w1 = model_->ItemIndexByID(id_w1);
92 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
93
94 // Create a ShelfItem for the second window.
95 ShelfID id_w2 = CreateShelfItem(window2);
96 EXPECT_EQ(3, model_->item_count());
97
98 int index_w2 = model_->ItemIndexByID(id_w2);
99 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
100
101 // ShelfItem is removed when its window property is cleared.
102 window1->ClearShelfItemDetails();
103 EXPECT_EQ(2, model_->item_count());
104 window2->ClearShelfItemDetails();
105 EXPECT_EQ(1, model_->item_count());
106 // Clearing twice doesn't do anything.
107 window2->ClearShelfItemDetails();
108 EXPECT_EQ(1, model_->item_count());
109}
110
111TEST_F(ShelfWindowWatcherTest, ActivateWindow) {
112 // ShelfModel only have APP_LIST item.
113 EXPECT_EQ(1, model_->item_count());
114 std::unique_ptr<views::Widget> widget1 =
115 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
116 WmWindow* window1 = WmLookup::Get()->GetWindowForWidget(widget1.get());
117 std::unique_ptr<views::Widget> widget2 =
118 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
119 WmWindow* window2 = WmLookup::Get()->GetWindowForWidget(widget2.get());
120
121 // Create a ShelfItem for the first window.
122 ShelfID id_w1 = CreateShelfItem(window1);
123 EXPECT_EQ(2, model_->item_count());
124 int index_w1 = model_->ItemIndexByID(id_w1);
125 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
126
127 // Create a ShelfItem for the second window.
128 ShelfID id_w2 = CreateShelfItem(window2);
129 EXPECT_EQ(3, model_->item_count());
130 int index_w2 = model_->ItemIndexByID(id_w2);
131 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
132 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
133
134 // The ShelfItem for the first window is active when the window is activated.
135 widget1->Activate();
136 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w1].status);
137 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w2].status);
138
139 // The ShelfItem for the second window is active when the window is activated.
140 widget2->Activate();
141 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
142 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
143}
144
145TEST_F(ShelfWindowWatcherTest, UpdateWindowProperty) {
146 // ShelfModel only has an APP_LIST item.
147 EXPECT_EQ(1, model_->item_count());
148
149 std::unique_ptr<views::Widget> widget =
150 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
151 WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget.get());
152
153 // Create a ShelfItem for |window|.
154 ShelfID id = CreateShelfItem(window);
155 EXPECT_EQ(2, model_->item_count());
156
157 int index = model_->ItemIndexByID(id);
158 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
159
160 // Update ShelfItem for |window|.
161 ShelfItemDetails details;
162 details.type = TYPE_PLATFORM_APP;
163
164 window->SetShelfItemDetails(details);
165 // No new item is created after updating a launcher item.
166 EXPECT_EQ(2, model_->item_count());
167 // index and id are not changed after updating a launcher item.
168 EXPECT_EQ(index, model_->ItemIndexByID(id));
169 EXPECT_EQ(id, model_->items()[index].id);
170}
171
172TEST_F(ShelfWindowWatcherTest, MaximizeAndRestoreWindow) {
173 // ShelfModel only has an APP_LIST item.
174 EXPECT_EQ(1, model_->item_count());
175
176 std::unique_ptr<views::Widget> widget =
177 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
178 WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget.get());
179 wm::WindowState* window_state = window->GetWindowState();
180
181 // Create a ShelfItem for |window|.
182 ShelfID id = CreateShelfItem(window);
183 EXPECT_EQ(2, model_->item_count());
184
185 int index = model_->ItemIndexByID(id);
186 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
187
188 // Maximize window |window|.
189 EXPECT_FALSE(window_state->IsMaximized());
190 window_state->Maximize();
191 EXPECT_TRUE(window_state->IsMaximized());
192 // No new item is created after maximizing a window |window|.
193 EXPECT_EQ(2, model_->item_count());
194 // index and id are not changed after maximizing a window |window|.
195 EXPECT_EQ(index, model_->ItemIndexByID(id));
196 EXPECT_EQ(id, model_->items()[index].id);
197
198 // Restore window |window|.
199 window_state->Restore();
200 EXPECT_FALSE(window_state->IsMaximized());
201 // No new item is created after restoring a window |window|.
202 EXPECT_EQ(2, model_->item_count());
203 // Index and id are not changed after maximizing a window |window|.
204 EXPECT_EQ(index, model_->ItemIndexByID(id));
205 EXPECT_EQ(id, model_->items()[index].id);
206}
207
208// Check that an item is maintained when its associated Window is docked.
209TEST_F(ShelfWindowWatcherTest, DockWindow) {
210 // ShelfModel only has an APP_LIST item.
211 EXPECT_EQ(1, model_->item_count());
212
213 std::unique_ptr<views::Widget> widget =
214 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
215 WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget.get());
216
217 // Create a ShelfItem for |window|.
218 ShelfID id = CreateShelfItem(window);
219 EXPECT_EQ(2, model_->item_count());
220
221 int index = model_->ItemIndexByID(id);
222 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
223
224 WmWindow* root_window = window->GetRootWindow();
225 WmWindow* default_container =
226 root_window->GetChildByShellWindowId(kShellWindowId_DefaultContainer);
227 EXPECT_EQ(default_container, window->GetParent());
228
229 WmWindow* docked_container =
230 root_window->GetChildByShellWindowId(kShellWindowId_DockedContainer);
231
232 // Check |window|'s item is not removed when it is re-parented to the dock.
233 docked_container->AddChild(window);
234 EXPECT_EQ(docked_container, window->GetParent());
235 EXPECT_EQ(2, model_->item_count());
236
237 // The shelf item is removed when the window is closed, even if it is in the
238 // docked container at the time.
239 widget.reset();
240 EXPECT_EQ(1, model_->item_count());
241}
242
243// Check |window|'s item is not changed during the dragging.
244// TODO(simonhong): Add a test for removing a Window during the dragging.
245TEST_F(ShelfWindowWatcherTest, DragWindow) {
246 // ShelfModel only has an APP_LIST item.
247 EXPECT_EQ(1, model_->item_count());
248
249 std::unique_ptr<views::Widget> widget =
250 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
251 WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget.get());
252
253 // Create a ShelfItem for |window|.
254 ShelfID id = CreateShelfItem(window);
255 EXPECT_EQ(2, model_->item_count());
256
257 int index = model_->ItemIndexByID(id);
258 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
259
260 // Simulate dragging of |window| and check its item is not changed.
261 std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
262 window, gfx::Point(), HTCAPTION, aura::client::WINDOW_MOVE_SOURCE_MOUSE));
263 ASSERT_TRUE(resizer.get());
264 resizer->Drag(gfx::Point(50, 50), 0);
265 resizer->CompleteDrag();
266
267 // Index and id are not changed after dragging a |window|.
268 EXPECT_EQ(index, model_->ItemIndexByID(id));
269 EXPECT_EQ(id, model_->items()[index].id);
270}
271
272} // namespace ash