blob: 9b9f3d7f12bf73ccb0fc497abfe58cd6e88c9dd8 [file] [log] [blame]
jamescook@chromium.org9c66adc2012-01-05 02:10:161// Copyright (c) 2012 The Chromium Authors. All rights reserved.
xiyuan@chromium.org488b42042011-11-15 00:20:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
sky@chromium.org55de57d2012-09-06 04:29:025#include "ash/shell.h"
6
7#include <algorithm>
Mitsuru Oshima04b54d02017-10-09 14:22:458#include <memory>
Ahmed Fakhry6b034bd2019-04-22 15:16:129#include <queue>
sky@chromium.org55de57d2012-09-06 04:29:0210#include <vector>
11
varunjain@chromium.orgc086bab2013-06-06 21:46:4412#include "ash/display/mouse_cursor_event_filter.h"
13#include "ash/drag_drop/drag_drop_controller.h"
James Cookeb426b52018-09-17 16:45:1214#include "ash/drag_drop/drag_drop_controller_test_api.h"
Darren Shencb2508442019-07-03 21:48:2315#include "ash/keyboard/ui/keyboard_ui_controller.h"
Darren Shen50e14952019-05-14 03:40:4316#include "ash/keyboard/ui/keyboard_util.h"
Xiyuan Xia14619a22019-05-14 20:20:4417#include "ash/public/cpp/ash_prefs.h"
Darren Shencd7d584d2019-05-15 01:30:3518#include "ash/public/cpp/keyboard/keyboard_switches.h"
jamescook8800b8232016-10-19 12:46:2719#include "ash/public/cpp/shell_window_ids.h"
Jun Mukai44986382019-05-14 18:19:2020#include "ash/public/cpp/test/shell_test_api.h"
oshima@chromium.org88d71122012-10-18 07:11:0121#include "ash/root_window_controller.h"
Xiyuan Xiae7b19542019-05-06 23:05:1822#include "ash/session/session_controller_impl.h"
James Cook346c8c62017-07-18 19:38:3723#include "ash/session/test_session_controller_client.h"
Angus L. M. McLean IVaa6378e2020-09-30 18:52:2024#include "ash/shelf/home_button.h"
James Cook840177e2017-05-25 02:20:0125#include "ash/shelf/shelf.h"
James Cookb0bf8e82017-04-09 17:01:4426#include "ash/shelf/shelf_layout_manager.h"
Angus L. M. McLean IVaa6378e2020-09-30 18:52:2027#include "ash/shelf/shelf_navigation_widget.h"
James Cookb0bf8e82017-04-09 17:01:4428#include "ash/shelf/shelf_widget.h"
Angus L. M. McLean IVaa6378e2020-09-30 18:52:2029#include "ash/system/status_area_widget.h"
ben@chromium.org1dd1c1b2012-02-17 22:04:4730#include "ash/test/ash_test_base.h"
James Cook8532dbc2017-07-31 21:54:5131#include "ash/test/ash_test_helper.h"
Mitsuru Oshima0c59d072021-01-13 17:53:5832#include "ash/test/test_widget_builder.h"
James Cook8532dbc2017-07-31 21:54:5133#include "ash/test_shell_delegate.h"
James Cookb0bf8e82017-04-09 17:01:4434#include "ash/wallpaper/wallpaper_widget_controller.h"
Ahmed Fakhryf929d5f2019-04-11 02:22:4835#include "ash/wm/desks/desks_util.h"
Angus L. M. McLean IVaa6378e2020-09-30 18:52:2036#include "ash/wm/overview/overview_controller.h"
okac21941d2017-06-20 17:54:4437#include "base/command_line.h"
Ahmed Fakhry6b034bd2019-04-22 15:16:1238#include "base/containers/flat_set.h"
avi@chromium.orga4ea1f12013-06-07 18:37:0739#include "base/strings/utf_string_conversions.h"
gab41aedcb12016-05-11 17:37:0140#include "base/threading/thread_task_runner_handle.h"
Alexander Alekseev3f09a8f2018-05-03 02:52:1041#include "components/account_id/account_id.h"
sky@chromium.orgff0278852013-11-05 22:35:4842#include "ui/aura/env.h"
xiyuan@chromium.org488b42042011-11-15 00:20:1843#include "ui/aura/window.h"
ben@chromium.orgfcc51c952014-02-21 21:31:2644#include "ui/aura/window_event_dispatcher.h"
flackr@chromium.org9c52d5e2013-08-20 09:47:0345#include "ui/base/models/simple_menu_model.h"
Joel Hockey784a8322020-05-20 21:19:2546#include "ui/display/scoped_display_for_new_windows.h"
tapted@chromium.org73c9fd02014-07-28 01:48:5247#include "ui/events/test/event_generator.h"
sadrul@chromium.orge703dfe2013-11-25 21:41:5048#include "ui/events/test/events_test_utils.h"
tdanderson@google.comcd9f71d2014-03-20 21:54:2149#include "ui/events/test/test_event_handler.h"
Avi Drissmanfefc2f82014-12-22 19:25:2950#include "ui/gfx/geometry/size.h"
flackr@chromium.org9c52d5e2013-08-20 09:47:0351#include "ui/views/controls/menu/menu_controller.h"
52#include "ui/views/controls/menu/menu_runner.h"
tfarina@chromium.orgc13be0d2011-11-22 02:09:5853#include "ui/views/widget/widget.h"
nkostylev@chromium.org55bdb502011-11-29 20:26:2554#include "ui/views/widget/widget_delegate.h"
dpolukhin@chromium.org71a75712013-05-30 18:59:2455#include "ui/views/window/dialog_delegate.h"
xiyuan@chromium.org488b42042011-11-15 00:20:1856
jamescook@chromium.org615922f2012-02-07 02:41:1557using aura::RootWindow;
58
ben@chromium.org55f593352011-12-24 05:42:4659namespace ash {
xiyuan@chromium.org488b42042011-11-15 00:20:1860
61namespace {
62
Ahmed Fakhryf929d5f2019-04-11 02:22:4863aura::Window* GetActiveDeskContainer() {
oshima@chromium.org093b8d642014-04-03 20:59:2864 return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
Ahmed Fakhryf929d5f2019-04-11 02:22:4865 desks_util::GetActiveDeskContainerId());
xiyuan@chromium.org488b42042011-11-15 00:20:1866}
67
68aura::Window* GetAlwaysOnTopContainer() {
oshima@chromium.org093b8d642014-04-03 20:59:2869 return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
70 kShellWindowId_AlwaysOnTopContainer);
xiyuan@chromium.org488b42042011-11-15 00:20:1871}
72
jamescook@chromium.orgb0079a92012-01-25 20:13:3873// Expect ALL the containers!
74void ExpectAllContainers() {
ben@chromium.orgbf9cdb362013-10-25 19:22:4575 aura::Window* root_window = Shell::GetPrimaryRootWindow();
Ahmed Fakhry6b034bd2019-04-22 15:16:1276
77 // Validate no duplicate container IDs.
78 base::flat_set<int> container_ids;
79 std::queue<aura::Window*> window_queue;
80 window_queue.push(root_window);
81 while (!window_queue.empty()) {
82 aura::Window* current_window = window_queue.front();
83 window_queue.pop();
84 for (aura::Window* child : current_window->children())
85 window_queue.push(child);
86
Allen Bauer6d2399c2021-05-13 16:06:2587 const int id = current_window->GetId();
Ahmed Fakhry6b034bd2019-04-22 15:16:1288
89 // Skip windows with no IDs.
90 if (id == aura::Window::kInitialId)
91 continue;
92
93 EXPECT_TRUE(container_ids.insert(id).second)
94 << "Found duplicate ID: " << id
95 << " at window: " << current_window->GetName();
96 }
97
msw607227f82016-08-30 17:22:3998 EXPECT_TRUE(
99 Shell::GetContainer(root_window, kShellWindowId_WallpaperContainer));
Ahmed Fakhry6b034bd2019-04-22 15:16:12100
101 for (int desk_id : desks_util::GetDesksContainersIds())
102 EXPECT_TRUE(Shell::GetContainer(root_window, desk_id));
103
oshima@chromium.org093b8d642014-04-03 20:59:28104 EXPECT_TRUE(
105 Shell::GetContainer(root_window, kShellWindowId_AlwaysOnTopContainer));
oshima@chromium.org093b8d642014-04-03 20:59:28106 EXPECT_TRUE(Shell::GetContainer(root_window, kShellWindowId_ShelfContainer));
107 EXPECT_TRUE(
108 Shell::GetContainer(root_window, kShellWindowId_SystemModalContainer));
msw607227f82016-08-30 17:22:39109 EXPECT_TRUE(Shell::GetContainer(root_window,
110 kShellWindowId_LockScreenWallpaperContainer));
oshima@chromium.org093b8d642014-04-03 20:59:28111 EXPECT_TRUE(
112 Shell::GetContainer(root_window, kShellWindowId_LockScreenContainer));
113 EXPECT_TRUE(Shell::GetContainer(root_window,
114 kShellWindowId_LockSystemModalContainer));
oshima@chromium.org093b8d642014-04-03 20:59:28115 EXPECT_TRUE(Shell::GetContainer(root_window, kShellWindowId_MenuContainer));
116 EXPECT_TRUE(Shell::GetContainer(root_window,
117 kShellWindowId_DragImageAndTooltipContainer));
118 EXPECT_TRUE(
119 Shell::GetContainer(root_window, kShellWindowId_SettingBubbleContainer));
120 EXPECT_TRUE(
121 Shell::GetContainer(root_window, kShellWindowId_OverlayContainer));
bshec3875422014-09-29 13:21:30122 EXPECT_TRUE(Shell::GetContainer(root_window,
123 kShellWindowId_ImeWindowParentContainer));
Yuichiro Hanada0c5b0782017-12-04 08:05:32124 EXPECT_TRUE(Shell::GetContainer(root_window,
125 kShellWindowId_VirtualKeyboardContainer));
oshima@chromium.org093b8d642014-04-03 20:59:28126 EXPECT_TRUE(
127 Shell::GetContainer(root_window, kShellWindowId_MouseCursorContainer));
James Cook9793f01d2017-08-14 16:56:23128
129 // Phantom window is not a container.
130 EXPECT_EQ(0u, container_ids.count(kShellWindowId_PhantomWindow));
131 EXPECT_FALSE(Shell::GetContainer(root_window, kShellWindowId_PhantomWindow));
jamescook@chromium.orgb0079a92012-01-25 20:13:38132}
133
Elly Fong-Jonesbc575992020-10-02 23:13:18134std::unique_ptr<views::WidgetDelegateView> CreateModalWidgetDelegate() {
Elly Fong-Jonesc5a0df532020-08-25 12:51:47135 auto delegate = std::make_unique<views::WidgetDelegateView>();
136 delegate->SetCanResize(true);
137 delegate->SetModalType(ui::MODAL_TYPE_SYSTEM);
Elly Fong-Jonesbc575992020-10-02 23:13:18138 delegate->SetOwnedByWidget(true);
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48139 delegate->SetTitle(u"Modal Window");
Elly Fong-Jonesbc575992020-10-02 23:13:18140 return delegate;
Elly Fong-Jonesc5a0df532020-08-25 12:51:47141}
James Cook43e5034d2018-06-01 20:51:17142
flackr@chromium.org9c52d5e2013-08-20 09:47:03143class SimpleMenuDelegate : public ui::SimpleMenuModel::Delegate {
144 public:
Chris Watkinsc24daf62017-11-28 03:43:09145 SimpleMenuDelegate() = default;
Peter Boströmec31a042021-09-16 23:37:34146
147 SimpleMenuDelegate(const SimpleMenuDelegate&) = delete;
148 SimpleMenuDelegate& operator=(const SimpleMenuDelegate&) = delete;
149
Chris Watkinsc24daf62017-11-28 03:43:09150 ~SimpleMenuDelegate() override = default;
flackr@chromium.org9c52d5e2013-08-20 09:47:03151
dcheng1f4538e2014-10-27 23:57:05152 bool IsCommandIdChecked(int command_id) const override { return false; }
153
154 bool IsCommandIdEnabled(int command_id) const override { return true; }
155
dcheng1f4538e2014-10-27 23:57:05156 void ExecuteCommand(int command_id, int event_flags) override {}
flackr@chromium.org9c52d5e2013-08-20 09:47:03157};
158
xiyuan@chromium.org488b42042011-11-15 00:20:18159} // namespace
160
James Cook317781a2017-07-18 02:08:06161class ShellTest : public AshTestBase {
erg@chromium.orga2e6af12013-01-07 21:40:35162 public:
erg@chromium.orga2e6af12013-01-07 21:40:35163 void TestCreateWindow(views::Widget::InitParams::Type type,
164 bool always_on_top,
165 aura::Window* expected_container) {
Mitsuru Oshima0c59d072021-01-13 17:53:58166 TestWidgetBuilder builder;
Avi Drissman9e6533282019-07-17 17:25:12167 if (always_on_top)
Mitsuru Oshima0c59d072021-01-13 17:53:58168 builder.SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
169 views::Widget* widget =
170 builder.SetWidgetType(type).BuildOwnedByNativeWidget();
erg@chromium.orga2e6af12013-01-07 21:40:35171
172 EXPECT_TRUE(
jamescookb8dcef522016-06-25 14:42:55173 expected_container->Contains(widget->GetNativeWindow()->parent()))
174 << "TestCreateWindow: type=" << type
175 << ", always_on_top=" << always_on_top;
erg@chromium.orga2e6af12013-01-07 21:40:35176
177 widget->Close();
flackr@chromium.org9c52d5e2013-08-20 09:47:03178 }
erg@chromium.orga2e6af12013-01-07 21:40:35179
flackr@chromium.org9c52d5e2013-08-20 09:47:03180 void LockScreenAndVerifyMenuClosed() {
181 // Verify a menu is open before locking.
182 views::MenuController* menu_controller =
183 views::MenuController::GetActiveInstance();
184 DCHECK(menu_controller);
Hwanseung Lee21aaa18d2019-04-20 01:14:51185 EXPECT_EQ(views::MenuController::ExitType::kNone,
186 menu_controller->exit_type());
flackr@chromium.org9c52d5e2013-08-20 09:47:03187
188 // Create a LockScreen window.
Mitsuru Oshima0c59d072021-01-13 17:53:58189 views::Widget* lock_widget =
190 TestWidgetBuilder()
191 .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW)
192 .SetShow(false)
193 .BuildOwnedByNativeWidget();
mswbc0a8b482016-06-30 02:21:14194 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
195 kShellWindowId_LockScreenContainer)
oshima@chromium.org093b8d642014-04-03 20:59:28196 ->AddChild(lock_widget->GetNativeView());
flackr@chromium.org9c52d5e2013-08-20 09:47:03197 lock_widget->Show();
xiyuan7ebbf7f2017-04-10 16:49:10198
199 // Simulate real screen locker to change session state to LOCKED
200 // when it is shown.
Xiyuan Xia04181462019-05-07 22:09:28201 GetSessionControllerClient()->LockScreen();
xiyuan7ebbf7f2017-04-10 16:49:10202
Xiyuan Xia04181462019-05-07 22:09:28203 SessionControllerImpl* controller = Shell::Get()->session_controller();
xiyuanf1ff14d2017-03-20 20:28:14204 EXPECT_TRUE(controller->IsScreenLocked());
flackr@chromium.org9c52d5e2013-08-20 09:47:03205 EXPECT_TRUE(lock_widget->GetNativeView()->HasFocus());
206
207 // Verify menu is closed.
jonross6d38f592017-03-14 19:34:33208 EXPECT_EQ(nullptr, views::MenuController::GetActiveInstance());
flackr@chromium.org9c52d5e2013-08-20 09:47:03209 lock_widget->Close();
xiyuanf1ff14d2017-03-20 20:28:14210 GetSessionControllerClient()->UnlockScreen();
flackr@chromium.org9c52d5e2013-08-20 09:47:03211 }
erg@chromium.orga2e6af12013-01-07 21:40:35212};
xiyuan@chromium.org488b42042011-11-15 00:20:18213
214TEST_F(ShellTest, CreateWindow) {
215 // Normal window should be created in default container.
216 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
217 false, // always_on_top
Ahmed Fakhryf929d5f2019-04-11 02:22:48218 GetActiveDeskContainer());
xiyuan@chromium.org488b42042011-11-15 00:20:18219 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
220 false, // always_on_top
Ahmed Fakhryf929d5f2019-04-11 02:22:48221 GetActiveDeskContainer());
xiyuan@chromium.org488b42042011-11-15 00:20:18222
223 // Always-on-top window and popup are created in always-on-top container.
224 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
225 true, // always_on_top
226 GetAlwaysOnTopContainer());
227 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
228 true, // always_on_top
229 GetAlwaysOnTopContainer());
230}
231
James Cook43e5034d2018-06-01 20:51:17232// Verifies that a window with a preferred size is created centered on the
233// default display for new windows. Mojo apps like shortcut_viewer rely on this
234// behavior.
235TEST_F(ShellTest, CreateWindowWithPreferredSize) {
236 UpdateDisplay("1024x768,800x600");
237
238 aura::Window* secondary_root = Shell::GetAllRootWindows()[1];
Joel Hockey784a8322020-05-20 21:19:25239 display::ScopedDisplayForNewWindows scoped_display(secondary_root);
James Cook43e5034d2018-06-01 20:51:17240
241 views::Widget::InitParams params;
242 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
243 // Don't specify bounds, parent or context.
Elly Fong-Jonesc5a0df532020-08-25 12:51:47244 {
245 auto delegate = std::make_unique<views::WidgetDelegateView>();
246 delegate->SetPreferredSize(gfx::Size(400, 300));
247 params.delegate = delegate.release();
248 }
James Cook43e5034d2018-06-01 20:51:17249 views::Widget widget;
Peter Kasting97defc92020-03-05 18:49:02250 params.context = GetContext();
Ahmed Fakhry32f3c452019-08-01 16:36:34251 widget.Init(std::move(params));
James Cook43e5034d2018-06-01 20:51:17252
253 // Widget is centered on secondary display.
254 EXPECT_EQ(secondary_root, widget.GetNativeWindow()->GetRootWindow());
255 EXPECT_EQ(GetSecondaryDisplay().work_area().CenterPoint(),
256 widget.GetRestoredBounds().CenterPoint());
257}
258
Avi Drissman9e6533282019-07-17 17:25:12259TEST_F(ShellTest, ChangeZOrderLevel) {
Avi Drissman9e6533282019-07-17 17:25:12260 // Creates a normal window.
Mitsuru Oshima0c59d072021-01-13 17:53:58261 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
xiyuan@chromium.org488b42042011-11-15 00:20:18262
Ahmed Fakhryf929d5f2019-04-11 02:22:48263 // It should be in the active desk container.
jamescookb8dcef522016-06-25 14:42:55264 EXPECT_TRUE(
Ahmed Fakhryf929d5f2019-04-11 02:22:48265 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
xiyuan@chromium.org488b42042011-11-15 00:20:18266
Avi Drissman9e6533282019-07-17 17:25:12267 // Set the z-order to float.
268 widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
xiyuan@chromium.org488b42042011-11-15 00:20:18269 // And it should in always on top container now.
270 EXPECT_EQ(GetAlwaysOnTopContainer(), widget->GetNativeWindow()->parent());
271
Avi Drissman9e6533282019-07-17 17:25:12272 // Put the z-order back to normal.
273 widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
Ahmed Fakhryf929d5f2019-04-11 02:22:48274 // It should go back to the active desk container.
jamescookb8dcef522016-06-25 14:42:55275 EXPECT_TRUE(
Ahmed Fakhryf929d5f2019-04-11 02:22:48276 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
xiyuan@chromium.org488b42042011-11-15 00:20:18277
Avi Drissman9e6533282019-07-17 17:25:12278 // Set the z-order again to the normal value.
279 widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
Ahmed Fakhryf929d5f2019-04-11 02:22:48280 // Should have no effect and we are still in the the active desk container.
jamescookb8dcef522016-06-25 14:42:55281 EXPECT_TRUE(
Ahmed Fakhryf929d5f2019-04-11 02:22:48282 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
xiyuan@chromium.org488b42042011-11-15 00:20:18283
284 widget->Close();
285}
286
nkostylev@chromium.org55bdb502011-11-29 20:26:25287TEST_F(ShellTest, CreateModalWindow) {
nkostylev@chromium.org55bdb502011-11-29 20:26:25288 // Create a normal window.
Mitsuru Oshima0c59d072021-01-13 17:53:58289 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
nkostylev@chromium.org55bdb502011-11-29 20:26:25290
Ahmed Fakhryf929d5f2019-04-11 02:22:48291 // It should be in the active desk container.
jamescookb8dcef522016-06-25 14:42:55292 EXPECT_TRUE(
Ahmed Fakhryf929d5f2019-04-11 02:22:48293 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
nkostylev@chromium.org55bdb502011-11-29 20:26:25294
295 // Create a modal window.
296 views::Widget* modal_widget = views::Widget::CreateWindowWithParent(
Elly Fong-Jonesc5a0df532020-08-25 12:51:47297 CreateModalWidgetDelegate(), widget->GetNativeView());
nkostylev@chromium.org55bdb502011-11-29 20:26:25298 modal_widget->Show();
299
300 // It should be in modal container.
oshima@chromium.org7b0f7502012-06-11 00:12:39301 aura::Window* modal_container = Shell::GetContainer(
oshima@chromium.org093b8d642014-04-03 20:59:28302 Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
nkostylev@chromium.org55bdb502011-11-29 20:26:25303 EXPECT_EQ(modal_container, modal_widget->GetNativeWindow()->parent());
304
305 modal_widget->Close();
306 widget->Close();
307}
308
309TEST_F(ShellTest, CreateLockScreenModalWindow) {
Maksim Ivanov3f60737e2020-11-20 05:08:17310 // Create a normal window.
Mitsuru Oshima0c59d072021-01-13 17:53:58311 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
dpolukhin@chromium.org71a75712013-05-30 18:59:24312 EXPECT_TRUE(widget->GetNativeView()->HasFocus());
nkostylev@chromium.org55bdb502011-11-29 20:26:25313
Ahmed Fakhryf929d5f2019-04-11 02:22:48314 // It should be in the active desk container.
jamescookb8dcef522016-06-25 14:42:55315 EXPECT_TRUE(
Ahmed Fakhryf929d5f2019-04-11 02:22:48316 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
nkostylev@chromium.org55bdb502011-11-29 20:26:25317
Xiyuan Xia04181462019-05-07 22:09:28318 GetSessionControllerClient()->LockScreen();
nkostylev@chromium.org55bdb502011-11-29 20:26:25319 // Create a LockScreen window.
Mitsuru Oshima0c59d072021-01-13 17:53:58320 views::Widget* lock_widget =
321 TestWidgetBuilder().SetShow(false).BuildOwnedByNativeWidget();
mswbc0a8b482016-06-30 02:21:14322 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
323 kShellWindowId_LockScreenContainer)
oshima@chromium.org093b8d642014-04-03 20:59:28324 ->AddChild(lock_widget->GetNativeView());
nkostylev@chromium.org55bdb502011-11-29 20:26:25325 lock_widget->Show();
dpolukhin@chromium.org71a75712013-05-30 18:59:24326 EXPECT_TRUE(lock_widget->GetNativeView()->HasFocus());
nkostylev@chromium.org55bdb502011-11-29 20:26:25327
328 // It should be in LockScreen container.
oshima@chromium.org7b0f7502012-06-11 00:12:39329 aura::Window* lock_screen = Shell::GetContainer(
mswbc0a8b482016-06-30 02:21:14330 Shell::GetPrimaryRootWindow(), kShellWindowId_LockScreenContainer);
nkostylev@chromium.org55bdb502011-11-29 20:26:25331 EXPECT_EQ(lock_screen, lock_widget->GetNativeWindow()->parent());
332
333 // Create a modal window with a lock window as parent.
334 views::Widget* lock_modal_widget = views::Widget::CreateWindowWithParent(
Elly Fong-Jonesc5a0df532020-08-25 12:51:47335 CreateModalWidgetDelegate(), lock_widget->GetNativeView());
nkostylev@chromium.org55bdb502011-11-29 20:26:25336 lock_modal_widget->Show();
dpolukhin@chromium.org71a75712013-05-30 18:59:24337 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
nkostylev@chromium.org55bdb502011-11-29 20:26:25338
339 // It should be in LockScreen modal container.
oshima@chromium.org093b8d642014-04-03 20:59:28340 aura::Window* lock_modal_container =
341 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
mswbc0a8b482016-06-30 02:21:14342 kShellWindowId_LockSystemModalContainer);
nkostylev@chromium.org55bdb502011-11-29 20:26:25343 EXPECT_EQ(lock_modal_container,
344 lock_modal_widget->GetNativeWindow()->parent());
345
346 // Create a modal window with a normal window as parent.
347 views::Widget* modal_widget = views::Widget::CreateWindowWithParent(
Elly Fong-Jonesc5a0df532020-08-25 12:51:47348 CreateModalWidgetDelegate(), widget->GetNativeView());
nkostylev@chromium.org55bdb502011-11-29 20:26:25349 modal_widget->Show();
dpolukhin@chromium.org71a75712013-05-30 18:59:24350 // Window on lock screen shouldn't lost focus.
351 EXPECT_FALSE(modal_widget->GetNativeView()->HasFocus());
352 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
nkostylev@chromium.org55bdb502011-11-29 20:26:25353
354 // It should be in non-LockScreen modal container.
oshima@chromium.org7b0f7502012-06-11 00:12:39355 aura::Window* modal_container = Shell::GetContainer(
mswbc0a8b482016-06-30 02:21:14356 Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
nkostylev@chromium.org55bdb502011-11-29 20:26:25357 EXPECT_EQ(modal_container, modal_widget->GetNativeWindow()->parent());
358
Elly Fong-Jonesbc575992020-10-02 23:13:18359 // Modal widget without parent, caused crash see crbug.com/226141
dpolukhin@chromium.org71a75712013-05-30 18:59:24360 views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
Elly Fong-Jonesbc575992020-10-02 23:13:18361 CreateModalWidgetDelegate(), GetContext(), nullptr);
dpolukhin@chromium.org71a75712013-05-30 18:59:24362
363 modal_dialog->Show();
364 EXPECT_FALSE(modal_dialog->GetNativeView()->HasFocus());
365 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
366
367 modal_dialog->Close();
368 modal_widget->Close();
nkostylev@chromium.org55bdb502011-11-29 20:26:25369 modal_widget->Close();
370 lock_modal_widget->Close();
371 lock_widget->Close();
372 widget->Close();
373}
374
mazda@chromium.orgf7eb89c2011-12-13 09:48:54375TEST_F(ShellTest, IsScreenLocked) {
Xiyuan Xiae7b19542019-05-06 23:05:18376 SessionControllerImpl* controller = Shell::Get()->session_controller();
Xiyuan Xia04181462019-05-07 22:09:28377 GetSessionControllerClient()->LockScreen();
xiyuanf1ff14d2017-03-20 20:28:14378 EXPECT_TRUE(controller->IsScreenLocked());
379 GetSessionControllerClient()->UnlockScreen();
380 EXPECT_FALSE(controller->IsScreenLocked());
mazda@chromium.orgf7eb89c2011-12-13 09:48:54381}
382
flackr@chromium.org9c52d5e2013-08-20 09:47:03383TEST_F(ShellTest, LockScreenClosesActiveMenu) {
384 SimpleMenuDelegate menu_delegate;
dchenga94547472016-04-08 08:41:11385 std::unique_ptr<ui::SimpleMenuModel> menu_model(
flackr@chromium.org9c52d5e2013-08-20 09:47:03386 new ui::SimpleMenuModel(&menu_delegate));
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48387 menu_model->AddItem(0, u"Menu item");
mswad3d9552017-05-18 21:23:36388 views::Widget* widget = Shell::GetPrimaryRootWindowController()
msw607227f82016-08-30 17:22:39389 ->wallpaper_widget_controller()
Toni Barzic712399152018-02-15 17:38:40390 ->GetWidget();
jonross5ab7c2d2017-04-21 22:34:31391 std::unique_ptr<views::MenuRunner> menu_runner(
392 new views::MenuRunner(menu_model.get(), views::MenuRunner::CONTEXT_MENU));
flackr@chromium.org9c52d5e2013-08-20 09:47:03393
Charlene Yand29f92a2019-04-19 20:45:02394 menu_runner->RunMenuAt(widget, nullptr, gfx::Rect(),
Hwanseung Leee75bb632019-03-21 22:55:43395 views::MenuAnchorPosition::kTopLeft,
jonross5ab7c2d2017-04-21 22:34:31396 ui::MENU_SOURCE_MOUSE);
jonross19c31fa2017-03-14 13:33:34397 LockScreenAndVerifyMenuClosed();
flackr@chromium.org9c52d5e2013-08-20 09:47:03398}
399
oshima@chromium.org878479482013-09-18 10:29:19400TEST_F(ShellTest, ManagedWindowModeBasics) {
jamescook@chromium.orgb0079a92012-01-25 20:13:38401 // We start with the usual window containers.
402 ExpectAllContainers();
tfarina@chromium.org64936bf2013-11-14 19:48:36403 // Shelf is visible.
jamescook577c95b2016-08-30 04:03:54404 ShelfWidget* shelf_widget = GetPrimaryShelf()->shelf_widget();
tfarina@chromium.org864b58552013-12-19 04:19:38405 EXPECT_TRUE(shelf_widget->IsVisible());
tfarina@chromium.org64936bf2013-11-14 19:48:36406 // Shelf is at bottom-left of screen.
tfarina@chromium.org864b58552013-12-19 04:19:38407 EXPECT_EQ(0, shelf_widget->GetWindowBoundsInScreen().x());
riajiangdfdfc99e2016-11-29 05:37:47408 EXPECT_EQ(
409 Shell::GetPrimaryRootWindow()->GetHost()->GetBoundsInPixels().height(),
410 shelf_widget->GetWindowBoundsInScreen().bottom());
msw607227f82016-08-30 17:22:39411 // We have a wallpaper but not a bare layer.
antrim@chromium.orgb4ddc7a2012-08-07 04:17:32412 // TODO (antrim): enable once we find out why it fails component build.
msw607227f82016-08-30 17:22:39413 // WallpaperWidgetController* wallpaper =
antrim@chromium.orgb4ddc7a2012-08-07 04:17:32414 // Shell::GetPrimaryRootWindow()->
oshima@chromium.org093b8d642014-04-03 20:59:28415 // GetProperty(kWindowDesktopComponent);
msw607227f82016-08-30 17:22:39416 // EXPECT_TRUE(wallpaper);
417 // EXPECT_TRUE(wallpaper->widget());
418 // EXPECT_FALSE(wallpaper->layer());
jamescook@chromium.orgb0079a92012-01-25 20:13:38419
420 // Create a normal window. It is not maximized.
Mitsuru Oshima0c59d072021-01-13 17:53:58421 views::Widget* widget = TestWidgetBuilder()
422 .SetBounds(gfx::Rect(11, 22, 300, 400))
423 .BuildOwnedByNativeWidget();
jamescook@chromium.orgb0079a92012-01-25 20:13:38424 EXPECT_FALSE(widget->IsMaximized());
425
jamescook@chromium.orgb0079a92012-01-25 20:13:38426 // Clean up.
427 widget->Close();
428}
429
sadrul@chromium.orgd10f5ae32014-03-12 00:29:58430// Tests that the cursor-filter is ahead of the drag-drop controller in the
431// pre-target list.
varunjain@chromium.orgc086bab2013-06-06 21:46:44432TEST_F(ShellTest, TestPreTargetHandlerOrder) {
skycb4be5b2017-04-06 17:52:45433 Shell* shell = Shell::Get();
sadrul@chromium.orge703dfe2013-11-25 21:41:50434 ui::EventTargetTestApi test_api(shell);
Jun Mukai44986382019-05-14 18:19:20435 ShellTestApi shell_test_api;
varunjain@chromium.orgc086bab2013-06-06 21:46:44436
Katie Db68a5522018-03-30 18:47:36437 ui::EventHandlerList handlers = test_api.GetPreTargetHandlers();
sadrul@chromium.orgd10f5ae32014-03-12 00:29:58438 ui::EventHandlerList::const_iterator cursor_filter =
439 std::find(handlers.begin(), handlers.end(), shell->mouse_cursor_filter());
jamescookb8dcef522016-06-25 14:42:55440 ui::EventHandlerList::const_iterator drag_drop = std::find(
441 handlers.begin(), handlers.end(), shell_test_api.drag_drop_controller());
sadrul@chromium.orgd10f5ae32014-03-12 00:29:58442 EXPECT_NE(handlers.end(), cursor_filter);
443 EXPECT_NE(handlers.end(), drag_drop);
444 EXPECT_GT(drag_drop, cursor_filter);
varunjain@chromium.orgc086bab2013-06-06 21:46:44445}
446
sky@chromium.orgff0278852013-11-05 22:35:48447// Verifies an EventHandler added to Env gets notified from EventGenerator.
448TEST_F(ShellTest, EnvPreTargetHandler) {
tdanderson@google.comcd9f71d2014-03-20 21:54:21449 ui::test::TestEventHandler event_handler;
Jun Mukaic3b59292019-05-19 20:44:04450 aura::Env::GetInstance()->AddPreTargetHandler(&event_handler);
tapted@chromium.org73c9fd02014-07-28 01:48:52451 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
sky@chromium.orgff0278852013-11-05 22:35:48452 generator.MoveMouseBy(1, 1);
453 EXPECT_NE(0, event_handler.num_mouse_events());
Jun Mukaic3b59292019-05-19 20:44:04454 aura::Env::GetInstance()->RemovePreTargetHandler(&event_handler);
sky@chromium.orgff0278852013-11-05 22:35:48455}
456
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20457// Verifies that pressing tab on an empty shell (one with no windows visible)
458// will put focus on the shelf. This enables keyboard only users to get to the
459// shelf without knowing the more obscure accelerators. Tab should move focus to
460// the home button, shift + tab to the status widget. From there, normal shelf
461// tab behaviour takes over, and the shell no longer catches that event.
462TEST_F(ShellTest, NoWindowTabFocus) {
463 ExpectAllContainers();
464
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20465 StatusAreaWidget* status_area_widget =
466 GetPrimaryShelf()->status_area_widget();
467 ShelfNavigationWidget* home_button = GetPrimaryShelf()->navigation_widget();
468
469 // Create a normal window. It is not maximized.
470 auto widget = CreateTestWidget();
471
472 // Hit tab with window open, and expect that focus is not on the navigation
473 // widget or status widget.
James Cookc275bd62021-07-20 00:32:21474 PressAndReleaseKey(ui::VKEY_TAB);
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20475 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
476 EXPECT_FALSE(status_area_widget->GetNativeView()->HasFocus());
477
478 // Minimize the window, hit tab and expect that focus is on the launcher.
479 widget->Minimize();
James Cookc275bd62021-07-20 00:32:21480 PressAndReleaseKey(ui::VKEY_TAB);
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20481 EXPECT_TRUE(home_button->GetNativeView()->HasFocus());
482
483 // Show (to steal focus back before continuing testing) and close the window.
484 widget->Show();
485 widget->Close();
486 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
487
488 // Confirm that pressing tab when overview mode is open does not go to home
489 // button. Tab should be handled by overview mode and not hit the shell event
490 // handler.
minch38d1e592021-07-02 19:30:25491 EnterOverview();
James Cookc275bd62021-07-20 00:32:21492 PressAndReleaseKey(ui::VKEY_TAB);
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20493 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
minch38d1e592021-07-02 19:30:25494 ExitOverview();
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20495
496 // Hit shift tab and expect that focus is on status widget.
James Cookc275bd62021-07-20 00:32:21497 PressAndReleaseKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
Angus L. M. McLean IVaa6378e2020-09-30 18:52:20498 EXPECT_TRUE(status_area_widget->GetNativeView()->HasFocus());
499}
500
sky@chromium.org5924a0b2012-04-27 17:02:28501// This verifies WindowObservers are removed when a window is destroyed after
502// the Shell is destroyed. This scenario (aura::Windows being deleted after the
503// Shell) occurs if someone is holding a reference to an unparented Window, as
504// is the case with a RenderWidgetHostViewAura that isn't on screen. As long as
505// everything is ok, we won't crash. If there is a bug, window's destructor will
506// notify some deleted object (say VideoDetector or ActivationController) and
507// this will crash.
James Cook317781a2017-07-18 02:08:06508class ShellTest2 : public AshTestBase {
sky@chromium.org5924a0b2012-04-27 17:02:28509 public:
Chris Watkinsc24daf62017-11-28 03:43:09510 ShellTest2() = default;
Peter Boströmec31a042021-09-16 23:37:34511
512 ShellTest2(const ShellTest2&) = delete;
513 ShellTest2& operator=(const ShellTest2&) = delete;
514
Chris Watkinsc24daf62017-11-28 03:43:09515 ~ShellTest2() override = default;
sky@chromium.org5924a0b2012-04-27 17:02:28516
517 protected:
dchenga94547472016-04-08 08:41:11518 std::unique_ptr<aura::Window> window_;
sky@chromium.org5924a0b2012-04-27 17:02:28519};
520
521TEST_F(ShellTest2, DontCrashWhenWindowDeleted) {
Jun Mukai4e4adb12019-05-17 16:46:46522 window_ = std::make_unique<aura::Window>(nullptr,
523 aura::client::WINDOW_TYPE_UNKNOWN);
danakjb161836d2015-04-03 05:14:18524 window_->Init(ui::LAYER_NOT_DRAWN);
sky@chromium.org5924a0b2012-04-27 17:02:28525}
526
James Cookeb426b52018-09-17 16:45:12527using ShellLoginTest = NoSessionAshTestBase;
528
529TEST_F(ShellLoginTest, DragAndDropDisabledBeforeLogin) {
530 DragDropController* drag_drop_controller =
Jun Mukai44986382019-05-14 18:19:20531 ShellTestApi().drag_drop_controller();
James Cookeb426b52018-09-17 16:45:12532 DragDropControllerTestApi drag_drop_controller_test_api(drag_drop_controller);
533 EXPECT_FALSE(drag_drop_controller_test_api.enabled());
534
535 SimulateUserLogin("user1@test.com");
536 EXPECT_TRUE(drag_drop_controller_test_api.enabled());
537}
538
Ahmed Fakhrye4a2c872020-01-30 22:34:42539using NoDuplicateShellContainerIdsTest = AshTestBase;
Ahmed Fakhry6b034bd2019-04-22 15:16:12540
Ahmed Fakhrye4a2c872020-01-30 22:34:42541TEST_F(NoDuplicateShellContainerIdsTest, ValidateContainersIds) {
Ahmed Fakhry6b034bd2019-04-22 15:16:12542 ExpectAllContainers();
543}
544
ben@chromium.org55f593352011-12-24 05:42:46545} // namespace ash