blob: 8f663acd304d1796b35dcfe067e99ce8944c77af [file] [log] [blame]
James Cookb0bf8e82017-04-09 17:01:441// 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/shelf/shelf_window_watcher.h"
6
Mitsuru Oshima04b54d02017-10-09 14:22:457#include <memory>
8
skye5fd1222017-04-12 18:43:239#include "ash/public/cpp/config.h"
James Cookb0bf8e82017-04-09 17:01:4410#include "ash/public/cpp/shelf_item.h"
msw109806d2017-06-02 20:11:5711#include "ash/public/cpp/shelf_model.h"
James Cookb0bf8e82017-04-09 17:01:4412#include "ash/public/cpp/shell_window_ids.h"
13#include "ash/public/cpp/window_properties.h"
14#include "ash/root_window_controller.h"
15#include "ash/session/session_controller.h"
James Cookb0bf8e82017-04-09 17:01:4416#include "ash/shell.h"
17#include "ash/test/ash_test_base.h"
18#include "ash/wm/window_resizer.h"
19#include "ash/wm/window_state.h"
msw19b30c2c2017-06-01 03:21:4020#include "third_party/skia/include/core/SkBitmap.h"
21#include "ui/aura/client/aura_constants.h"
James Cookb0bf8e82017-04-09 17:01:4422#include "ui/aura/window.h"
23#include "ui/base/hit_test.h"
msw19b30c2c2017-06-01 03:21:4024#include "ui/base/resource/resource_bundle.h"
25#include "ui/gfx/image/image_skia.h"
26#include "ui/resources/grit/ui_resources.h"
James Cookb0bf8e82017-04-09 17:01:4427#include "ui/views/widget/widget.h"
msw70ac45f2017-06-05 02:02:4528#include "ui/wm/core/transient_window_controller.h"
James Cookb0bf8e82017-04-09 17:01:4429
30namespace ash {
msw19b30c2c2017-06-01 03:21:4031namespace {
32
33// Create a test 1x1 icon image with a given |color|.
34gfx::ImageSkia CreateImageSkiaIcon(SkColor color) {
35 SkBitmap bitmap;
36 bitmap.allocN32Pixels(1, 1);
37 bitmap.eraseColor(color);
38 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
39}
James Cookb0bf8e82017-04-09 17:01:4440
James Cook317781a2017-07-18 02:08:0641class ShelfWindowWatcherTest : public AshTestBase {
James Cookb0bf8e82017-04-09 17:01:4442 public:
43 ShelfWindowWatcherTest() : model_(nullptr) {}
44 ~ShelfWindowWatcherTest() override {}
45
46 void SetUp() override {
James Cook317781a2017-07-18 02:08:0647 AshTestBase::SetUp();
James Cookb0bf8e82017-04-09 17:01:4448 model_ = Shell::Get()->shelf_model();
Mike Wasserman717cd572017-09-23 17:01:4049 // ShelfModel creates an app list item.
50 ASSERT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4451 }
52
53 void TearDown() override {
54 model_ = nullptr;
James Cook317781a2017-07-18 02:08:0655 AshTestBase::TearDown();
James Cookb0bf8e82017-04-09 17:01:4456 }
57
msw6958e7f2017-05-15 22:55:0658 static ShelfID CreateShelfItem(aura::Window* window) {
msw84b8a5f2017-05-05 00:13:3659 static int id = 0;
msw70ac45f2017-06-05 02:02:4560 ShelfID shelf_id(std::to_string(id++));
msw6958e7f2017-05-15 22:55:0661 window->SetProperty(kShelfIDKey, new std::string(shelf_id.Serialize()));
62 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
msw84b8a5f2017-05-05 00:13:3663 return shelf_id;
James Cookb0bf8e82017-04-09 17:01:4464 }
65
66 protected:
67 ShelfModel* model_;
68
69 private:
70 DISALLOW_COPY_AND_ASSIGN(ShelfWindowWatcherTest);
71};
72
73// Ensure shelf items are added and removed as windows are opened and closed.
74TEST_F(ShelfWindowWatcherTest, OpenAndClose) {
msw70ac45f2017-06-05 02:02:4575 // Windows with valid ShelfItemType and ShelfID properties get shelf items.
James Cookb0bf8e82017-04-09 17:01:4476 std::unique_ptr<views::Widget> widget1 =
77 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:0678 CreateShelfItem(widget1->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:4079 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4480 std::unique_ptr<views::Widget> widget2 =
81 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:0682 CreateShelfItem(widget2->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:4083 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4484
85 // Each ShelfItem is removed when the associated window is destroyed.
86 widget1.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:2087 EXPECT_EQ(2, model_->item_count());
Mike Wasserman717cd572017-09-23 17:01:4088 widget2.reset();
89 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:4490}
91
mswfeae4322017-06-08 04:24:2292// Ensure shelf items are added and removed for some unknown windows in mash.
msw70ac45f2017-06-05 02:02:4593TEST_F(ShelfWindowWatcherTest, OpenAndCloseMash) {
94 if (Shell::GetAshConfig() != Config::MASH)
95 return;
96
msw70ac45f2017-06-05 02:02:4597 // Windows with no valid ShelfItemType and ShelfID properties get shelf items.
98 std::unique_ptr<views::Widget> widget1 =
99 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Mike Wasserman717cd572017-09-23 17:01:40100 EXPECT_EQ(2, model_->item_count());
msw70ac45f2017-06-05 02:02:45101 std::unique_ptr<views::Widget> widget2 =
102 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Mike Wasserman717cd572017-09-23 17:01:40103 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:45104
105 // Each ShelfItem is removed when the associated window is destroyed.
106 widget1.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20107 EXPECT_EQ(2, model_->item_count());
Mike Wasserman717cd572017-09-23 17:01:40108 widget2.reset();
109 EXPECT_EQ(1, model_->item_count());
msw70ac45f2017-06-05 02:02:45110
mswfeae4322017-06-08 04:24:22111 // Windows with type WINDOW_TYPE_NORMAL get shelf items, others do not.
112 aura::client::WindowType no_item_types[] = {
113 aura::client::WINDOW_TYPE_UNKNOWN, aura::client::WINDOW_TYPE_NORMAL,
114 aura::client::WINDOW_TYPE_POPUP, aura::client::WINDOW_TYPE_CONTROL,
115 aura::client::WINDOW_TYPE_PANEL, aura::client::WINDOW_TYPE_MENU,
116 aura::client::WINDOW_TYPE_TOOLTIP};
117 for (aura::client::WindowType type : no_item_types) {
118 std::unique_ptr<aura::Window> window =
Mitsuru Oshima04b54d02017-10-09 14:22:45119 std::make_unique<aura::Window>(nullptr, type);
mswfeae4322017-06-08 04:24:22120 window->Init(ui::LAYER_NOT_DRAWN);
121 Shell::GetPrimaryRootWindow()
122 ->GetChildById(kShellWindowId_DefaultContainer)
123 ->AddChild(window.get());
124 window->Show();
Mike Wasserman717cd572017-09-23 17:01:40125 EXPECT_EQ(type == aura::client::WINDOW_TYPE_NORMAL ? 2 : 1,
mswfeae4322017-06-08 04:24:22126 model_->item_count());
127 }
128
msw70ac45f2017-06-05 02:02:45129 // Windows with WindowState::ignored_by_shelf set do not get shelf items.
130 widget1 =
131 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
132 wm::GetWindowState(widget1->GetNativeWindow())->set_ignored_by_shelf(true);
133 // TODO(msw): Make the flag a window property and remove this workaround.
134 widget1->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey,
135 true);
Mike Wasserman717cd572017-09-23 17:01:40136 EXPECT_EQ(1, model_->item_count());
msw70ac45f2017-06-05 02:02:45137}
138
James Cookb0bf8e82017-04-09 17:01:44139TEST_F(ShelfWindowWatcherTest, CreateAndRemoveShelfItemProperties) {
140 // TODO: investigate failure in mash. http://crbug.com/695562.
skye5fd1222017-04-12 18:43:23141 if (Shell::GetAshConfig() == Config::MASH)
James Cookb0bf8e82017-04-09 17:01:44142 return;
143
James Cookb0bf8e82017-04-09 17:01:44144 // Creating windows without a valid ShelfItemType does not add items.
Mike Wasserman717cd572017-09-23 17:01:40145 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44146 std::unique_ptr<views::Widget> widget1 =
147 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44148 std::unique_ptr<views::Widget> widget2 =
149 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
Mike Wasserman717cd572017-09-23 17:01:40150 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44151
152 // Create a ShelfItem for the first window.
msw6958e7f2017-05-15 22:55:06153 ShelfID id_w1 = CreateShelfItem(widget1->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40154 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44155
156 int index_w1 = model_->ItemIndexByID(id_w1);
157 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
158
159 // Create a ShelfItem for the second window.
msw6958e7f2017-05-15 22:55:06160 ShelfID id_w2 = CreateShelfItem(widget2->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40161 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44162
163 int index_w2 = model_->ItemIndexByID(id_w2);
164 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
165
166 // ShelfItem is removed when the item type window property is cleared.
msw6958e7f2017-05-15 22:55:06167 widget1->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
168 static_cast<int32_t>(TYPE_UNDEFINED));
Mike Wasserman717cd572017-09-23 17:01:40169 EXPECT_EQ(2, model_->item_count());
msw6958e7f2017-05-15 22:55:06170 widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
171 static_cast<int32_t>(TYPE_UNDEFINED));
Mike Wasserman717cd572017-09-23 17:01:40172 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44173 // Clearing twice doesn't do anything.
msw6958e7f2017-05-15 22:55:06174 widget2->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
175 static_cast<int32_t>(TYPE_UNDEFINED));
Mike Wasserman717cd572017-09-23 17:01:40176 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44177}
178
179TEST_F(ShelfWindowWatcherTest, ActivateWindow) {
180 // TODO: investigate failure in mash. http://crbug.com/695562.
skye5fd1222017-04-12 18:43:23181 if (Shell::GetAshConfig() == Config::MASH)
James Cookb0bf8e82017-04-09 17:01:44182 return;
183
James Cookb0bf8e82017-04-09 17:01:44184 std::unique_ptr<views::Widget> widget1 =
185 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44186 std::unique_ptr<views::Widget> widget2 =
187 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
James Cookb0bf8e82017-04-09 17:01:44188
189 // Create a ShelfItem for the first window.
msw6958e7f2017-05-15 22:55:06190 ShelfID id_w1 = CreateShelfItem(widget1->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40191 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44192 int index_w1 = model_->ItemIndexByID(id_w1);
193 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
194
195 // Create a ShelfItem for the second window.
msw6958e7f2017-05-15 22:55:06196 ShelfID id_w2 = CreateShelfItem(widget2->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40197 EXPECT_EQ(3, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44198 int index_w2 = model_->ItemIndexByID(id_w2);
199 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
200 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
201
202 // The ShelfItem for the first window is active when the window is activated.
203 widget1->Activate();
204 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w1].status);
205 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w2].status);
206
207 // The ShelfItem for the second window is active when the window is activated.
208 widget2->Activate();
209 EXPECT_EQ(STATUS_RUNNING, model_->items()[index_w1].status);
210 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index_w2].status);
211}
212
213TEST_F(ShelfWindowWatcherTest, UpdateWindowProperty) {
Michael Wasserman78b6f3e2017-07-20 19:51:20214 // Create a ShelfItem for a new window.
Mike Wasserman717cd572017-09-23 17:01:40215 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44216 std::unique_ptr<views::Widget> widget =
217 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06218 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40219 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44220
221 int index = model_->ItemIndexByID(id);
222 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
223
msw6958e7f2017-05-15 22:55:06224 // Update the window's ShelfItemType.
225 widget->GetNativeWindow()->SetProperty(kShelfItemTypeKey,
mswfeae4322017-06-08 04:24:22226 static_cast<int32_t>(TYPE_APP_PANEL));
James Cookb0bf8e82017-04-09 17:01:44227 // No new item is created after updating a launcher item.
Mike Wasserman717cd572017-09-23 17:01:40228 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44229 // index and id are not changed after updating a launcher item.
230 EXPECT_EQ(index, model_->ItemIndexByID(id));
231 EXPECT_EQ(id, model_->items()[index].id);
232}
233
234TEST_F(ShelfWindowWatcherTest, MaximizeAndRestoreWindow) {
Michael Wasserman78b6f3e2017-07-20 19:51:20235 // Create a ShelfItem for a new window.
Mike Wasserman717cd572017-09-23 17:01:40236 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44237 std::unique_ptr<views::Widget> widget =
238 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06239 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40240 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44241
242 int index = model_->ItemIndexByID(id);
243 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
244
msw6958e7f2017-05-15 22:55:06245 // Maximize the window.
Michael Wasserman78b6f3e2017-07-20 19:51:20246 wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeWindow());
James Cookb0bf8e82017-04-09 17:01:44247 EXPECT_FALSE(window_state->IsMaximized());
248 window_state->Maximize();
249 EXPECT_TRUE(window_state->IsMaximized());
msw6958e7f2017-05-15 22:55:06250 // No new item is created after maximizing the window.
Mike Wasserman717cd572017-09-23 17:01:40251 EXPECT_EQ(2, model_->item_count());
msw6958e7f2017-05-15 22:55:06252 // index and id are not changed after maximizing the window.
James Cookb0bf8e82017-04-09 17:01:44253 EXPECT_EQ(index, model_->ItemIndexByID(id));
254 EXPECT_EQ(id, model_->items()[index].id);
255
msw6958e7f2017-05-15 22:55:06256 // Restore the window.
James Cookb0bf8e82017-04-09 17:01:44257 window_state->Restore();
258 EXPECT_FALSE(window_state->IsMaximized());
msw6958e7f2017-05-15 22:55:06259 // No new item is created after restoring the window.
Mike Wasserman717cd572017-09-23 17:01:40260 EXPECT_EQ(2, model_->item_count());
msw6958e7f2017-05-15 22:55:06261 // Index and id are not changed after maximizing the window.
James Cookb0bf8e82017-04-09 17:01:44262 EXPECT_EQ(index, model_->ItemIndexByID(id));
263 EXPECT_EQ(id, model_->items()[index].id);
264}
265
266// Check |window|'s item is not changed during the dragging.
267// TODO(simonhong): Add a test for removing a Window during the dragging.
268TEST_F(ShelfWindowWatcherTest, DragWindow) {
Michael Wasserman78b6f3e2017-07-20 19:51:20269 // Create a ShelfItem for a new window.
Mike Wasserman717cd572017-09-23 17:01:40270 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44271 std::unique_ptr<views::Widget> widget =
272 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06273 ShelfID id = CreateShelfItem(widget->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40274 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44275
276 int index = model_->ItemIndexByID(id);
277 EXPECT_EQ(STATUS_ACTIVE, model_->items()[index].status);
278
msw6958e7f2017-05-15 22:55:06279 // Simulate dragging of the window and check its item is not changed.
skya5e9a122017-05-22 20:45:35280 std::unique_ptr<WindowResizer> resizer(
281 CreateWindowResizer(widget->GetNativeWindow(), gfx::Point(), HTCAPTION,
Thiago Farina3b086a02017-05-30 22:32:50282 ::wm::WINDOW_MOVE_SOURCE_MOUSE));
James Cookb0bf8e82017-04-09 17:01:44283 ASSERT_TRUE(resizer.get());
284 resizer->Drag(gfx::Point(50, 50), 0);
285 resizer->CompleteDrag();
286
msw6958e7f2017-05-15 22:55:06287 // Index and id are not changed after dragging the window.
James Cookb0bf8e82017-04-09 17:01:44288 EXPECT_EQ(index, model_->ItemIndexByID(id));
289 EXPECT_EQ(id, model_->items()[index].id);
290}
291
mswfeae4322017-06-08 04:24:22292// Ensure panels and dialogs get shelf items.
293TEST_F(ShelfWindowWatcherTest, PanelAndDialogWindows) {
mswfeae4322017-06-08 04:24:22294 // An item is created for a dialog window.
Mike Wasserman717cd572017-09-23 17:01:40295 EXPECT_EQ(1, model_->item_count());
mswfeae4322017-06-08 04:24:22296 std::unique_ptr<views::Widget> dialog_widget =
msw6958e7f2017-05-15 22:55:06297 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
mswfeae4322017-06-08 04:24:22298 aura::Window* dialog = dialog_widget->GetNativeWindow();
299 dialog->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
300 dialog->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
Mike Wasserman717cd572017-09-23 17:01:40301 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44302
mswfeae4322017-06-08 04:24:22303 // An item is created for a panel window.
James Cookb0bf8e82017-04-09 17:01:44304 views::Widget panel_widget;
305 views::Widget::InitParams panel_params(views::Widget::InitParams::TYPE_PANEL);
306 panel_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
Scott Violet66193f72017-06-26 22:24:18307 panel_params.parent = Shell::GetPrimaryRootWindow()->GetChildById(
308 kShellWindowId_PanelContainer);
James Cookb0bf8e82017-04-09 17:01:44309 panel_widget.Init(panel_params);
310 panel_widget.Show();
mswfeae4322017-06-08 04:24:22311 aura::Window* panel = panel_widget.GetNativeWindow();
312 panel->SetProperty(kShelfIDKey, new std::string(ShelfID("b").Serialize()));
313 panel->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP_PANEL));
Mike Wasserman717cd572017-09-23 17:01:40314 EXPECT_EQ(3, model_->item_count());
mswfeae4322017-06-08 04:24:22315
316 // An item is not created for an app window.
317 std::unique_ptr<views::Widget> app_widget =
318 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
319 aura::Window* app = app_widget->GetNativeWindow();
320 app->SetProperty(kShelfIDKey, new std::string(ShelfID("c").Serialize()));
321 app->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_APP));
Mike Wasserman717cd572017-09-23 17:01:40322 EXPECT_EQ(3, model_->item_count());
mswfeae4322017-06-08 04:24:22323 app_widget.reset();
James Cookb0bf8e82017-04-09 17:01:44324
325 // Each ShelfItem is removed when the associated window is destroyed.
326 panel_widget.CloseNow();
Michael Wasserman78b6f3e2017-07-20 19:51:20327 EXPECT_EQ(2, model_->item_count());
Mike Wasserman717cd572017-09-23 17:01:40328 dialog_widget.reset();
329 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44330}
331
msw19b30c2c2017-06-01 03:21:40332// Ensure items use the app icon and window icon aura::Window properties.
333TEST_F(ShelfWindowWatcherTest, ItemIcon) {
msw19b30c2c2017-06-01 03:21:40334 // Create a ShelfItem for a window; it should have a default icon.
Mike Wasserman717cd572017-09-23 17:01:40335 EXPECT_EQ(1, model_->item_count());
msw19b30c2c2017-06-01 03:21:40336 std::unique_ptr<views::Widget> widget =
337 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
338 aura::Window* window = widget->GetNativeWindow();
339 ShelfID id = CreateShelfItem(window);
Mike Wasserman717cd572017-09-23 17:01:40340 EXPECT_EQ(2, model_->item_count());
msw19b30c2c2017-06-01 03:21:40341 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
342 gfx::Image default_image = rb.GetImageNamed(IDR_DEFAULT_FAVICON_32);
Mike Wasserman717cd572017-09-23 17:01:40343 EXPECT_TRUE(model_->items()[1].image.BackedBySameObjectAs(
msw19b30c2c2017-06-01 03:21:40344 default_image.AsImageSkia()));
345
346 // Setting a window icon should update the item icon.
347 const gfx::ImageSkia red = CreateImageSkiaIcon(SK_ColorRED);
348 window->SetProperty(aura::client::kWindowIconKey, new gfx::ImageSkia(red));
Mike Wasserman717cd572017-09-23 17:01:40349 EXPECT_EQ(SK_ColorRED, model_->items()[1].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40350
351 // Setting an app icon should override the window icon.
352 const gfx::ImageSkia blue = CreateImageSkiaIcon(SK_ColorBLUE);
353 window->SetProperty(aura::client::kAppIconKey, new gfx::ImageSkia(blue));
Mike Wasserman717cd572017-09-23 17:01:40354 EXPECT_EQ(SK_ColorBLUE, model_->items()[1].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40355
356 // Clearing the app icon should restore the window icon to the shelf item.
357 window->ClearProperty(aura::client::kAppIconKey);
Mike Wasserman717cd572017-09-23 17:01:40358 EXPECT_EQ(SK_ColorRED, model_->items()[1].image.bitmap()->getColor(0, 0));
msw19b30c2c2017-06-01 03:21:40359}
360
James Cookb0bf8e82017-04-09 17:01:44361TEST_F(ShelfWindowWatcherTest, DontCreateShelfEntriesForChildWindows) {
Mike Wasserman717cd572017-09-23 17:01:40362 EXPECT_EQ(1, model_->item_count());
mswfeae4322017-06-08 04:24:22363 std::unique_ptr<aura::Window> window =
Mitsuru Oshima04b54d02017-10-09 14:22:45364 std::make_unique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
James Cookb0bf8e82017-04-09 17:01:44365 window->Init(ui::LAYER_NOT_DRAWN);
mswfeae4322017-06-08 04:24:22366 window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
367 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
James Cookb0bf8e82017-04-09 17:01:44368 Shell::GetPrimaryRootWindow()
369 ->GetChildById(kShellWindowId_DefaultContainer)
370 ->AddChild(window.get());
371 window->Show();
Mike Wasserman717cd572017-09-23 17:01:40372 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44373
mswfeae4322017-06-08 04:24:22374 std::unique_ptr<aura::Window> child =
Mitsuru Oshima04b54d02017-10-09 14:22:45375 std::make_unique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
mswfeae4322017-06-08 04:24:22376 child->Init(ui::LAYER_NOT_DRAWN);
377 child->SetProperty(kShelfIDKey, new std::string(ShelfID("b").Serialize()));
378 child->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
379 window->AddChild(child.get());
380 child->Show();
381 // There should not be a new shelf item for |child|.
Mike Wasserman717cd572017-09-23 17:01:40382 EXPECT_EQ(2, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44383
mswfeae4322017-06-08 04:24:22384 child.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20385 EXPECT_EQ(2, model_->item_count());
Mike Wasserman717cd572017-09-23 17:01:40386 window.reset();
387 EXPECT_EQ(1, model_->item_count());
James Cookb0bf8e82017-04-09 17:01:44388}
389
mswfeae4322017-06-08 04:24:22390TEST_F(ShelfWindowWatcherTest, CreateShelfEntriesForTransientWindows) {
Mike Wasserman717cd572017-09-23 17:01:40391 EXPECT_EQ(1, model_->item_count());
mswfeae4322017-06-08 04:24:22392 std::unique_ptr<aura::Window> window =
Mitsuru Oshima04b54d02017-10-09 14:22:45393 std::make_unique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
msw70ac45f2017-06-05 02:02:45394 window->Init(ui::LAYER_NOT_DRAWN);
mswfeae4322017-06-08 04:24:22395 window->SetProperty(kShelfIDKey, new std::string(ShelfID("a").Serialize()));
396 window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
msw70ac45f2017-06-05 02:02:45397 Shell::GetPrimaryRootWindow()
398 ->GetChildById(kShellWindowId_DefaultContainer)
399 ->AddChild(window.get());
400 window->Show();
Mike Wasserman717cd572017-09-23 17:01:40401 EXPECT_EQ(2, model_->item_count());
msw70ac45f2017-06-05 02:02:45402
mswfeae4322017-06-08 04:24:22403 std::unique_ptr<aura::Window> transient =
Mitsuru Oshima04b54d02017-10-09 14:22:45404 std::make_unique<aura::Window>(nullptr, aura::client::WINDOW_TYPE_NORMAL);
mswfeae4322017-06-08 04:24:22405 transient->Init(ui::LAYER_NOT_DRAWN);
406 transient->SetProperty(kShelfIDKey,
407 new std::string(ShelfID("b").Serialize()));
408 transient->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
409 Shell::GetPrimaryRootWindow()
410 ->GetChildById(kShellWindowId_DefaultContainer)
411 ->AddChild(transient.get());
412 ::wm::TransientWindowController::Get()->AddTransientChild(window.get(),
413 transient.get());
414 transient->Show();
415 // There should be a new shelf item for |transient|.
Mike Wasserman717cd572017-09-23 17:01:40416 EXPECT_EQ(3, model_->item_count());
msw70ac45f2017-06-05 02:02:45417
mswfeae4322017-06-08 04:24:22418 transient.reset();
Michael Wasserman78b6f3e2017-07-20 19:51:20419 EXPECT_EQ(2, model_->item_count());
Mike Wasserman717cd572017-09-23 17:01:40420 window.reset();
421 EXPECT_EQ(1, model_->item_count());
msw70ac45f2017-06-05 02:02:45422}
423
James Cookb0bf8e82017-04-09 17:01:44424// Ensures ShelfWindowWatcher supports windows opened prior to session start.
James Cook317781a2017-07-18 02:08:06425using ShelfWindowWatcherSessionStartTest = NoSessionAshTestBase;
James Cookb0bf8e82017-04-09 17:01:44426TEST_F(ShelfWindowWatcherSessionStartTest, PreExistingWindow) {
427 ShelfModel* model = Shell::Get()->shelf_model();
428 ASSERT_FALSE(
429 Shell::Get()->session_controller()->IsActiveUserSessionStarted());
430
Mike Wasserman717cd572017-09-23 17:01:40431 // ShelfModel creates an app list item.
432 EXPECT_EQ(1, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44433
434 // Construct a window that should get a shelf item once the session starts.
435 std::unique_ptr<views::Widget> widget =
436 CreateTestWidget(nullptr, kShellWindowId_DefaultContainer, gfx::Rect());
msw6958e7f2017-05-15 22:55:06437 ShelfWindowWatcherTest::CreateShelfItem(widget->GetNativeWindow());
Mike Wasserman717cd572017-09-23 17:01:40438 EXPECT_EQ(1, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44439
440 // Start the test user session; ShelfWindowWatcher will find the open window.
Xiyuan Xiaffbc92032017-08-21 18:36:13441 CreateUserSessions(1);
Mike Wasserman717cd572017-09-23 17:01:40442 EXPECT_EQ(2, model->item_count());
James Cookb0bf8e82017-04-09 17:01:44443}
444
msw19b30c2c2017-06-01 03:21:40445} // namespace
James Cookb0bf8e82017-04-09 17:01:44446} // namespace ash