OLD | NEW |
| (Empty) |
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 "ash/common/shelf/shelf_window_watcher.h" | |
6 | |
7 #include "ash/common/session/session_state_delegate.h" | |
8 #include "ash/common/shelf/shelf_item_types.h" | |
9 #include "ash/common/shelf/shelf_model.h" | |
10 #include "ash/common/wm/window_resizer.h" | |
11 #include "ash/common/wm/window_state.h" | |
12 #include "ash/common/wm_shell.h" | |
13 #include "ash/common/wm_window.h" | |
14 #include "ash/public/cpp/shell_window_ids.h" | |
15 #include "ash/public/cpp/window_properties.h" | |
16 #include "ash/root_window_controller.h" | |
17 #include "ash/test/ash_test_base.h" | |
18 #include "ui/base/hit_test.h" | |
19 #include "ui/views/widget/widget.h" | |
20 | |
21 namespace ash { | |
22 | |
23 class ShelfWindowWatcherTest : public test::AshTestBase { | |
24 public: | |
25 ShelfWindowWatcherTest() : model_(nullptr) {} | |
26 ~ShelfWindowWatcherTest() override {} | |
27 | |
28 void SetUp() override { | |
29 test::AshTestBase::SetUp(); | |
30 model_ = WmShell::Get()->shelf_model(); | |
31 } | |
32 | |
33 void TearDown() override { | |
34 model_ = nullptr; | |
35 test::AshTestBase::TearDown(); | |
36 } | |
37 | |
38 static ShelfID CreateShelfItem(WmWindow* window) { | |
39 ShelfID id = WmShell::Get()->shelf_model()->next_id(); | |
40 window->aura_window()->SetProperty(kShelfItemTypeKey, | |
41 static_cast<int32_t>(TYPE_DIALOG)); | |
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. | |
53 TEST_F(ShelfWindowWatcherTest, OpenAndClose) { | |
54 // ShelfModel only has an APP_LIST item. | |
55 EXPECT_EQ(1, model_->item_count()); | |
56 | |
57 // Adding windows with valid ShelfItemType properties adds shelf items. | |
58 std::unique_ptr<views::Widget> widget1 = | |
59 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
60 CreateShelfItem(WmWindow::Get(widget1->GetNativeWindow())); | |
61 EXPECT_EQ(2, model_->item_count()); | |
62 std::unique_ptr<views::Widget> widget2 = | |
63 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
64 CreateShelfItem(WmWindow::Get(widget2->GetNativeWindow())); | |
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 | |
74 TEST_F(ShelfWindowWatcherTest, CreateAndRemoveShelfItemProperties) { | |
75 // TODO: investigate failure in mash. http://crbug.com/695562. | |
76 if (WmShell::Get()->IsRunningInMash()) | |
77 return; | |
78 | |
79 // ShelfModel only has an APP_LIST item. | |
80 EXPECT_EQ(1, model_->item_count()); | |
81 | |
82 // Creating windows without a valid ShelfItemType does not add items. | |
83 std::unique_ptr<views::Widget> widget1 = | |
84 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
85 WmWindow* window1 = WmWindow::Get(widget1->GetNativeWindow()); | |
86 std::unique_ptr<views::Widget> widget2 = | |
87 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
88 WmWindow* window2 = WmWindow::Get(widget2->GetNativeWindow()); | |
89 EXPECT_EQ(1, model_->item_count()); | |
90 | |
91 // Create a ShelfItem for the first window. | |
92 ShelfID id_w1 = CreateShelfItem(window1); | |
93 EXPECT_EQ(2, model_->item_count()); | |
94 | |
95 int index_w1 = model_->ItemIndexByID(id_w1); | |
96 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status); | |
97 | |
98 // Create a ShelfItem for the second window. | |
99 ShelfID id_w2 = CreateShelfItem(window2); | |
100 EXPECT_EQ(3, model_->item_count()); | |
101 | |
102 int index_w2 = model_->ItemIndexByID(id_w2); | |
103 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status); | |
104 | |
105 // ShelfItem is removed when the item type window property is cleared. | |
106 window1->aura_window()->SetProperty(kShelfItemTypeKey, | |
107 static_cast<int32_t>(TYPE_UNDEFINED)); | |
108 EXPECT_EQ(2, model_->item_count()); | |
109 window2->aura_window()->SetProperty(kShelfItemTypeKey, | |
110 static_cast<int32_t>(TYPE_UNDEFINED)); | |
111 EXPECT_EQ(1, model_->item_count()); | |
112 // Clearing twice doesn't do anything. | |
113 window2->aura_window()->SetProperty(kShelfItemTypeKey, | |
114 static_cast<int32_t>(TYPE_UNDEFINED)); | |
115 EXPECT_EQ(1, model_->item_count()); | |
116 } | |
117 | |
118 TEST_F(ShelfWindowWatcherTest, ActivateWindow) { | |
119 // TODO: investigate failure in mash. http://crbug.com/695562. | |
120 if (WmShell::Get()->IsRunningInMash()) | |
121 return; | |
122 | |
123 // ShelfModel only have APP_LIST item. | |
124 EXPECT_EQ(1, model_->item_count()); | |
125 std::unique_ptr<views::Widget> widget1 = | |
126 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
127 WmWindow* window1 = WmWindow::Get(widget1->GetNativeWindow()); | |
128 std::unique_ptr<views::Widget> widget2 = | |
129 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
130 WmWindow* window2 = WmWindow::Get(widget2->GetNativeWindow()); | |
131 | |
132 // Create a ShelfItem for the first window. | |
133 ShelfID id_w1 = CreateShelfItem(window1); | |
134 EXPECT_EQ(2, model_->item_count()); | |
135 int index_w1 = model_->ItemIndexByID(id_w1); | |
136 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status); | |
137 | |
138 // Create a ShelfItem for the second window. | |
139 ShelfID id_w2 = CreateShelfItem(window2); | |
140 EXPECT_EQ(3, model_->item_count()); | |
141 int index_w2 = model_->ItemIndexByID(id_w2); | |
142 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status); | |
143 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status); | |
144 | |
145 // The ShelfItem for the first window is active when the window is activated. | |
146 widget1->Activate(); | |
147 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w1].status); | |
148 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w2].status); | |
149 | |
150 // The ShelfItem for the second window is active when the window is activated. | |
151 widget2->Activate(); | |
152 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status); | |
153 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status); | |
154 } | |
155 | |
156 TEST_F(ShelfWindowWatcherTest, UpdateWindowProperty) { | |
157 // TODO: investigate failure in mash. http://crbug.com/695562. | |
158 if (WmShell::Get()->IsRunningInMash()) | |
159 return; | |
160 | |
161 // ShelfModel only has an APP_LIST item. | |
162 EXPECT_EQ(1, model_->item_count()); | |
163 | |
164 std::unique_ptr<views::Widget> widget = | |
165 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
166 WmWindow* window = WmWindow::Get(widget->GetNativeWindow()); | |
167 | |
168 // Create a ShelfItem for |window|. | |
169 ShelfID id = CreateShelfItem(window); | |
170 EXPECT_EQ(2, model_->item_count()); | |
171 | |
172 int index = model_->ItemIndexByID(id); | |
173 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status); | |
174 | |
175 // Update the ShelfItemType for |window|. | |
176 window->aura_window()->SetProperty(kShelfItemTypeKey, | |
177 static_cast<int32_t>(TYPE_APP)); | |
178 // No new item is created after updating a launcher item. | |
179 EXPECT_EQ(2, model_->item_count()); | |
180 // index and id are not changed after updating a launcher item. | |
181 EXPECT_EQ(index, model_->ItemIndexByID(id)); | |
182 EXPECT_EQ(id, model_->items()[index].id); | |
183 } | |
184 | |
185 TEST_F(ShelfWindowWatcherTest, MaximizeAndRestoreWindow) { | |
186 // TODO: investigate failure in mash. http://crbug.com/695562. | |
187 if (WmShell::Get()->IsRunningInMash()) | |
188 return; | |
189 | |
190 // ShelfModel only has an APP_LIST item. | |
191 EXPECT_EQ(1, model_->item_count()); | |
192 | |
193 std::unique_ptr<views::Widget> widget = | |
194 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
195 WmWindow* window = WmWindow::Get(widget->GetNativeWindow()); | |
196 wm::WindowState* window_state = window->GetWindowState(); | |
197 | |
198 // Create a ShelfItem for |window|. | |
199 ShelfID id = CreateShelfItem(window); | |
200 EXPECT_EQ(2, model_->item_count()); | |
201 | |
202 int index = model_->ItemIndexByID(id); | |
203 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status); | |
204 | |
205 // Maximize window |window|. | |
206 EXPECT_FALSE(window_state->IsMaximized()); | |
207 window_state->Maximize(); | |
208 EXPECT_TRUE(window_state->IsMaximized()); | |
209 // No new item is created after maximizing a window |window|. | |
210 EXPECT_EQ(2, model_->item_count()); | |
211 // index and id are not changed after maximizing a window |window|. | |
212 EXPECT_EQ(index, model_->ItemIndexByID(id)); | |
213 EXPECT_EQ(id, model_->items()[index].id); | |
214 | |
215 // Restore window |window|. | |
216 window_state->Restore(); | |
217 EXPECT_FALSE(window_state->IsMaximized()); | |
218 // No new item is created after restoring a window |window|. | |
219 EXPECT_EQ(2, model_->item_count()); | |
220 // Index and id are not changed after maximizing a window |window|. | |
221 EXPECT_EQ(index, model_->ItemIndexByID(id)); | |
222 EXPECT_EQ(id, model_->items()[index].id); | |
223 } | |
224 | |
225 // Check that an item is maintained when its associated Window is docked. | |
226 TEST_F(ShelfWindowWatcherTest, DockWindow) { | |
227 // TODO: investigate failure in mash. http://crbug.com/695562. | |
228 if (WmShell::Get()->IsRunningInMash()) | |
229 return; | |
230 | |
231 // ShelfModel only has an APP_LIST item. | |
232 EXPECT_EQ(1, model_->item_count()); | |
233 | |
234 std::unique_ptr<views::Widget> widget = | |
235 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
236 WmWindow* window = WmWindow::Get(widget->GetNativeWindow()); | |
237 | |
238 // Create a ShelfItem for |window|. | |
239 ShelfID id = CreateShelfItem(window); | |
240 EXPECT_EQ(2, model_->item_count()); | |
241 | |
242 int index = model_->ItemIndexByID(id); | |
243 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status); | |
244 | |
245 WmWindow* root_window = window->GetRootWindow(); | |
246 WmWindow* default_container = | |
247 root_window->GetChildByShellWindowId(kShellWindowId_DefaultContainer); | |
248 EXPECT_EQ(default_container, window->GetParent()); | |
249 | |
250 WmWindow* docked_container = | |
251 root_window->GetChildByShellWindowId(kShellWindowId_DockedContainer); | |
252 | |
253 // Check |window|'s item is not removed when it is re-parented to the dock. | |
254 docked_container->AddChild(window); | |
255 EXPECT_EQ(docked_container, window->GetParent()); | |
256 EXPECT_EQ(2, model_->item_count()); | |
257 | |
258 // The shelf item is removed when the window is closed, even if it is in the | |
259 // docked container at the time. | |
260 widget.reset(); | |
261 EXPECT_EQ(1, model_->item_count()); | |
262 } | |
263 | |
264 // Check |window|'s item is not changed during the dragging. | |
265 // TODO(simonhong): Add a test for removing a Window during the dragging. | |
266 TEST_F(ShelfWindowWatcherTest, DragWindow) { | |
267 // TODO: investigate failure in mash. http://crbug.com/695562. | |
268 if (WmShell::Get()->IsRunningInMash()) | |
269 return; | |
270 | |
271 // ShelfModel only has an APP_LIST item. | |
272 EXPECT_EQ(1, model_->item_count()); | |
273 | |
274 std::unique_ptr<views::Widget> widget = | |
275 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
276 WmWindow* window = WmWindow::Get(widget->GetNativeWindow()); | |
277 | |
278 // Create a ShelfItem for |window|. | |
279 ShelfID id = CreateShelfItem(window); | |
280 EXPECT_EQ(2, model_->item_count()); | |
281 | |
282 int index = model_->ItemIndexByID(id); | |
283 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status); | |
284 | |
285 // Simulate dragging of |window| and check its item is not changed. | |
286 std::unique_ptr<WindowResizer> resizer(CreateWindowResizer( | |
287 window, gfx::Point(), HTCAPTION, aura::client::WINDOW_MOVE_SOURCE_MOUSE)); | |
288 ASSERT_TRUE(resizer.get()); | |
289 resizer->Drag(gfx::Point(50, 50), 0); | |
290 resizer->CompleteDrag(); | |
291 | |
292 // Index and id are not changed after dragging a |window|. | |
293 EXPECT_EQ(index, model_->ItemIndexByID(id)); | |
294 EXPECT_EQ(id, model_->items()[index].id); | |
295 } | |
296 | |
297 // Ensure shelf items are added and removed as panels are opened and closed. | |
298 TEST_F(ShelfWindowWatcherTest, PanelWindow) { | |
299 // TODO: investigate failure in mash. http://crbug.com/695562. | |
300 if (WmShell::Get()->IsRunningInMash()) | |
301 return; | |
302 | |
303 // ShelfModel only has an APP_LIST item. | |
304 EXPECT_EQ(1, model_->item_count()); | |
305 | |
306 // Adding windows with valid ShelfItemType properties adds shelf items. | |
307 std::unique_ptr<views::Widget> widget1 = | |
308 CreateTestWidget(nullptr, kShellWindowId_PanelContainer, gfx::Rect()); | |
309 WmWindow* window1 = WmWindow::Get(widget1->GetNativeWindow()); | |
310 window1->aura_window()->SetProperty(kShelfItemTypeKey, | |
311 static_cast<int32_t>(TYPE_APP_PANEL)); | |
312 EXPECT_EQ(2, model_->item_count()); | |
313 std::unique_ptr<views::Widget> widget2 = | |
314 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
315 WmWindow* window2 = WmWindow::Get(widget2->GetNativeWindow()); | |
316 window2->aura_window()->SetProperty(kShelfItemTypeKey, | |
317 static_cast<int32_t>(TYPE_APP_PANEL)); | |
318 EXPECT_EQ(3, model_->item_count()); | |
319 | |
320 // Create a panel-type widget to mimic Chrome's app panel windows. | |
321 views::Widget panel_widget; | |
322 views::Widget::InitParams panel_params(views::Widget::InitParams::TYPE_PANEL); | |
323 panel_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
324 WmShell::Get() | |
325 ->GetPrimaryRootWindow() | |
326 ->GetRootWindowController() | |
327 ->ConfigureWidgetInitParamsForContainer( | |
328 &panel_widget, kShellWindowId_PanelContainer, &panel_params); | |
329 panel_widget.Init(panel_params); | |
330 panel_widget.Show(); | |
331 WmWindow* panel_window = WmWindow::Get(panel_widget.GetNativeWindow()); | |
332 panel_window->aura_window()->SetProperty( | |
333 kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP_PANEL)); | |
334 EXPECT_EQ(4, model_->item_count()); | |
335 | |
336 // Each ShelfItem is removed when the associated window is destroyed. | |
337 panel_widget.CloseNow(); | |
338 EXPECT_EQ(3, model_->item_count()); | |
339 widget2.reset(); | |
340 EXPECT_EQ(2, model_->item_count()); | |
341 widget1.reset(); | |
342 EXPECT_EQ(1, model_->item_count()); | |
343 } | |
344 | |
345 TEST_F(ShelfWindowWatcherTest, DontCreateShelfEntriesForChildWindows) { | |
346 const int initial_item_count = model_->item_count(); | |
347 | |
348 WmWindow* window = WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_NORMAL, | |
349 ui::LAYER_NOT_DRAWN); | |
350 window->aura_window()->SetProperty(kShelfItemTypeKey, | |
351 static_cast<int32_t>(TYPE_APP)); | |
352 WmShell::Get() | |
353 ->GetPrimaryRootWindow() | |
354 ->GetChildByShellWindowId(kShellWindowId_DefaultContainer) | |
355 ->AddChild(window); | |
356 window->Show(); | |
357 EXPECT_EQ(initial_item_count + 1, model_->item_count()); | |
358 | |
359 WmWindow* child_window = WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_NORMAL, | |
360 ui::LAYER_NOT_DRAWN); | |
361 child_window->aura_window()->SetProperty(kShelfItemTypeKey, | |
362 static_cast<int32_t>(TYPE_APP)); | |
363 window->AddChild(child_window); | |
364 child_window->Show(); | |
365 // |child_window| should not result in adding a new entry. | |
366 EXPECT_EQ(initial_item_count + 1, model_->item_count()); | |
367 | |
368 child_window->Destroy(); | |
369 window->Destroy(); | |
370 EXPECT_EQ(initial_item_count, model_->item_count()); | |
371 } | |
372 | |
373 // Ensures ShelfWindowWatcher supports windows opened prior to session start. | |
374 using ShelfWindowWatcherSessionStartTest = test::NoSessionAshTestBase; | |
375 TEST_F(ShelfWindowWatcherSessionStartTest, PreExistingWindow) { | |
376 ShelfModel* model = WmShell::Get()->shelf_model(); | |
377 ASSERT_FALSE( | |
378 WmShell::Get()->GetSessionStateDelegate()->IsActiveUserSessionStarted()); | |
379 | |
380 // ShelfModel only has an APP_LIST item. | |
381 EXPECT_EQ(1, model->item_count()); | |
382 | |
383 // Construct a window that should get a shelf item once the session starts. | |
384 std::unique_ptr<views::Widget> widget = | |
385 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect()); | |
386 WmWindow* window = WmWindow::Get(widget->GetNativeWindow()); | |
387 ShelfWindowWatcherTest::CreateShelfItem(window); | |
388 EXPECT_EQ(1, model->item_count()); | |
389 | |
390 // Start the test user session; ShelfWindowWatcher will find the open window. | |
391 SetSessionStarted(true); | |
392 EXPECT_EQ(2, model->item_count()); | |
393 } | |
394 | |
395 } // namespace ash | |
OLD | NEW |