blob: bd396c54e3fe5e778b548af84f90a3bbbe8ead46 [file] [log] [blame]
[email protected]f1853122012-06-27 16:21:261// Copyright (c) 2012 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
[email protected]8674b312012-10-12 19:02:445#include "ash/root_window_controller.h"
6
dchenga94547472016-04-08 08:41:117#include <memory>
8
tdanderson0b7905b2016-06-22 21:53:039#include "ash/common/material_design/material_design_controller.h"
jamescook2b624c5a2016-06-08 01:34:0210#include "ash/common/session/session_state_delegate.h"
skyc096d9f2016-06-02 13:46:2611#include "ash/common/shell_window_ids.h"
jamescook2a4d1eb2016-06-09 20:10:0712#include "ash/common/system/tray/system_tray_delegate.h"
skyd6063772016-06-01 17:52:2113#include "ash/common/wm/window_state.h"
jamescook443e42d2016-06-10 21:44:4614#include "ash/common/wm_shell.h"
oshima38dffad2015-05-05 17:22:5615#include "ash/display/display_manager.h"
[email protected]f1853122012-06-27 16:21:2616#include "ash/shell.h"
tdanderson0b7905b2016-06-22 21:53:0317#include "ash/test/ash_md_test_base.h"
[email protected]f1853122012-06-27 16:21:2618#include "ash/test/ash_test_base.h"
oshimabba2d992015-05-22 19:21:3919#include "ash/test/display_manager_test_api.h"
[email protected]8674b312012-10-12 19:02:4420#include "ash/wm/system_modal_container_layout_manager.h"
[email protected]2ee2f5d2013-01-10 23:37:1621#include "ash/wm/window_properties.h"
sky8d5646fe2016-04-15 17:03:4622#include "ash/wm/window_state_aura.h"
[email protected]f1853122012-06-27 16:21:2623#include "ash/wm/window_util.h"
[email protected]eff4c7f2013-08-13 01:45:5024#include "base/command_line.h"
[email protected]792b9b12012-12-11 03:53:2725#include "ui/aura/client/focus_change_observer.h"
[email protected]8cfb6722012-11-28 03:28:4626#include "ui/aura/client/focus_client.h"
[email protected]e3225e02013-10-23 20:44:3727#include "ui/aura/client/window_tree_client.h"
[email protected]f1853122012-06-27 16:21:2628#include "ui/aura/env.h"
[email protected]dbf835d82012-09-11 18:23:0929#include "ui/aura/test/test_window_delegate.h"
30#include "ui/aura/test/test_windows.h"
[email protected]f1853122012-06-27 16:21:2631#include "ui/aura/window.h"
[email protected]fcc51c952014-02-21 21:31:2632#include "ui/aura/window_event_dispatcher.h"
[email protected]dbf835d82012-09-11 18:23:0933#include "ui/aura/window_tracker.h"
[email protected]2082d7d2014-05-13 14:44:2334#include "ui/base/ime/dummy_text_input_client.h"
35#include "ui/base/ime/input_method.h"
36#include "ui/base/ime/text_input_client.h"
[email protected]73c9fd02014-07-28 01:48:5237#include "ui/events/test/event_generator.h"
[email protected]cd9f71d2014-03-20 21:54:2138#include "ui/events/test/test_event_handler.h"
jamescookcf8b648f2016-06-01 19:58:1739#include "ui/keyboard/keyboard_controller.h"
[email protected]eff4c7f2013-08-13 01:45:5040#include "ui/keyboard/keyboard_switches.h"
ben974286a2015-10-10 00:45:1241#include "ui/keyboard/keyboard_ui.h"
[email protected]39e95212014-04-23 20:00:0142#include "ui/keyboard/keyboard_util.h"
[email protected]f1853122012-06-27 16:21:2643#include "ui/views/controls/menu/menu_controller.h"
44#include "ui/views/widget/widget.h"
45#include "ui/views/widget/widget_delegate.h"
46
[email protected]2ee2f5d2013-01-10 23:37:1647using aura::Window;
48using views::Widget;
49
[email protected]f1853122012-06-27 16:21:2650namespace ash {
51namespace {
52
53class TestDelegate : public views::WidgetDelegateView {
54 public:
55 explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {}
dcheng1f4538e2014-10-27 23:57:0556 ~TestDelegate() override {}
[email protected]f1853122012-06-27 16:21:2657
58 // Overridden from views::WidgetDelegate:
dcheng1f4538e2014-10-27 23:57:0559 views::View* GetContentsView() override { return this; }
[email protected]f1853122012-06-27 16:21:2660
dcheng1f4538e2014-10-27 23:57:0561 ui::ModalType GetModalType() const override {
[email protected]f1853122012-06-27 16:21:2662 return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
63 }
64
65 private:
66 bool system_modal_;
[email protected]0fbfa972013-10-02 19:23:3367
[email protected]f1853122012-06-27 16:21:2668 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
69};
70
[email protected]792b9b12012-12-11 03:53:2771class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate,
72 public aura::client::FocusChangeObserver {
[email protected]dbf835d82012-09-11 18:23:0973 public:
74 DeleteOnBlurDelegate() : window_(NULL) {}
dcheng1f4538e2014-10-27 23:57:0575 ~DeleteOnBlurDelegate() override {}
[email protected]dbf835d82012-09-11 18:23:0976
[email protected]792b9b12012-12-11 03:53:2777 void SetWindow(aura::Window* window) {
78 window_ = window;
79 aura::client::SetFocusChangeObserver(window_, this);
80 }
[email protected]dbf835d82012-09-11 18:23:0981
[email protected]869f6352012-12-06 20:47:1782 private:
[email protected]dbf835d82012-09-11 18:23:0983 // aura::test::TestWindowDelegate overrides:
dcheng1f4538e2014-10-27 23:57:0584 bool CanFocus() override { return true; }
[email protected]dbf835d82012-09-11 18:23:0985
[email protected]792b9b12012-12-11 03:53:2786 // aura::client::FocusChangeObserver implementation:
dcheng1f4538e2014-10-27 23:57:0587 void OnWindowFocused(aura::Window* gained_focus,
88 aura::Window* lost_focus) override {
[email protected]792b9b12012-12-11 03:53:2789 if (window_ == lost_focus)
90 delete window_;
[email protected]869f6352012-12-06 20:47:1791 }
92
[email protected]dbf835d82012-09-11 18:23:0993 aura::Window* window_;
94
95 DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate);
96};
97
[email protected]f1853122012-06-27 16:21:2698} // namespace
99
100namespace test {
[email protected]f1853122012-06-27 16:21:26101
tdanderson0b7905b2016-06-22 21:53:03102class RootWindowControllerTest : public AshMDTestBase {
[email protected]a2e6af12013-01-07 21:40:35103 public:
104 views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
105 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
106 NULL, CurrentContext(), bounds);
107 widget->Show();
108 return widget;
109 }
110
111 views::Widget* CreateModalWidget(const gfx::Rect& bounds) {
112 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
113 new TestDelegate(true), CurrentContext(), bounds);
114 widget->Show();
115 return widget;
116 }
117
118 views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds,
119 gfx::NativeWindow parent) {
jamescookb8dcef522016-06-25 14:42:55120 views::Widget* widget = views::Widget::CreateWindowWithParentAndBounds(
121 new TestDelegate(true), parent, bounds);
[email protected]a2e6af12013-01-07 21:40:35122 widget->Show();
123 return widget;
124 }
125
[email protected]c9390bd2013-11-08 20:33:13126 aura::Window* GetModalContainer(aura::Window* root_window) {
[email protected]093b8d642014-04-03 20:59:28127 return Shell::GetContainer(root_window,
128 ash::kShellWindowId_SystemModalContainer);
[email protected]a2e6af12013-01-07 21:40:35129 }
130};
[email protected]f1853122012-06-27 16:21:26131
tdanderson0b7905b2016-06-22 21:53:03132INSTANTIATE_TEST_CASE_P(
133 /* prefix intentionally left blank due to only one parameterization */,
134 RootWindowControllerTest,
135 testing::Values(MaterialDesignController::NON_MATERIAL,
136 MaterialDesignController::MATERIAL_NORMAL,
137 MaterialDesignController::MATERIAL_EXPERIMENTAL));
138
139TEST_P(RootWindowControllerTest, MoveWindows_Basic) {
[email protected]e75642a2013-06-12 17:21:18140 if (!SupportsMultipleDisplays())
141 return;
tdanderson0b7905b2016-06-22 21:53:03142 const int height_offset = GetMdMaximizedWindowHeightOffset();
143
[email protected]2816c2462013-12-17 02:22:25144 // Windows origin should be doubled when moved to the 1st display.
145 UpdateDisplay("600x600,300x300");
[email protected]c9390bd2013-11-08 20:33:13146 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]f1853122012-06-27 16:21:26147
148 views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100));
149 EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow());
[email protected]e2f64d102012-07-19 19:17:04150 EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString());
[email protected]8d625fb2012-07-18 16:40:06151 EXPECT_EQ("50,10 100x100",
[email protected]e2f64d102012-07-19 19:17:04152 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26153
154 views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100));
155 maximized->Maximize();
156 EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow());
tdanderson0b7905b2016-06-22 21:53:03157 EXPECT_EQ(gfx::Rect(600, 0, 300, 253 + height_offset).ToString(),
158 maximized->GetWindowBoundsInScreen().ToString());
159 EXPECT_EQ(gfx::Rect(0, 0, 300, 253 + height_offset).ToString(),
[email protected]8c0ec432013-05-10 04:33:39160 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26161
162 views::Widget* minimized = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
163 minimized->Minimize();
164 EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow());
jamescookb8dcef522016-06-25 14:42:55165 EXPECT_EQ("800,10 100x100", minimized->GetWindowBoundsInScreen().ToString());
[email protected]f1853122012-06-27 16:21:26166
[email protected]2816c2462013-12-17 02:22:25167 views::Widget* fullscreen = CreateTestWidget(gfx::Rect(850, 10, 100, 100));
[email protected]f1853122012-06-27 16:21:26168 fullscreen->SetFullscreen(true);
169 EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow());
[email protected]1a015382012-12-01 19:44:59170
jamescookb8dcef522016-06-25 14:42:55171 EXPECT_EQ("600,0 300x300", fullscreen->GetWindowBoundsInScreen().ToString());
[email protected]2816c2462013-12-17 02:22:25172 EXPECT_EQ("0,0 300x300",
[email protected]e2f64d102012-07-19 19:17:04173 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26174
[email protected]8f2f151412013-01-26 03:58:37175 views::Widget* unparented_control = new Widget;
176 Widget::InitParams params;
177 params.bounds = gfx::Rect(650, 10, 100, 100);
178 params.context = CurrentContext();
179 params.type = Widget::InitParams::TYPE_CONTROL;
180 unparented_control->Init(params);
181 EXPECT_EQ(root_windows[1],
182 unparented_control->GetNativeView()->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28183 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
[email protected]8f2f151412013-01-26 03:58:37184 unparented_control->GetNativeView()->parent()->id());
185
[email protected]95db9c12013-01-31 11:47:44186 aura::Window* panel = CreateTestWindowInShellWithDelegateAndType(
[email protected]5b251f12013-12-19 01:50:05187 NULL, ui::wm::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100));
[email protected]95db9c12013-01-31 11:47:44188 EXPECT_EQ(root_windows[1], panel->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28189 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
[email protected]95db9c12013-01-31 11:47:44190
[email protected]dbf835d82012-09-11 18:23:09191 // Make sure a window that will delete itself when losing focus
192 // will not crash.
193 aura::WindowTracker tracker;
194 DeleteOnBlurDelegate delete_on_blur_delegate;
[email protected]5ebe6102012-11-28 21:00:03195 aura::Window* d2 = CreateTestWindowInShellWithDelegate(
196 &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100));
[email protected]792b9b12012-12-11 03:53:27197 delete_on_blur_delegate.SetWindow(d2);
[email protected]550543e2013-01-11 22:43:44198 aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2);
[email protected]dbf835d82012-09-11 18:23:09199 tracker.Add(d2);
200
[email protected]f634dd32012-07-23 22:49:07201 UpdateDisplay("600x600");
[email protected]f1853122012-06-27 16:21:26202
[email protected]dbf835d82012-09-11 18:23:09203 // d2 must have been deleted.
204 EXPECT_FALSE(tracker.Contains(d2));
205
[email protected]f1853122012-06-27 16:21:26206 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
[email protected]2816c2462013-12-17 02:22:25207 EXPECT_EQ("100,20 100x100", normal->GetWindowBoundsInScreen().ToString());
208 EXPECT_EQ("100,20 100x100",
[email protected]e2f64d102012-07-19 19:17:04209 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26210
yiyix20e7d3f2016-06-14 21:49:36211 // Maximized area on primary display has 47px for non-md and 48px for md
212 // (defined in ash::SHELF_SIZE) inset at the bottom.
[email protected]2a64b0a2013-07-23 23:15:54213
214 // First clear fullscreen status, since both fullscreen and maximized windows
215 // share the same desktop workspace, which cancels the shelf status.
216 fullscreen->SetFullscreen(false);
[email protected]f1853122012-06-27 16:21:26217 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
tdanderson0b7905b2016-06-22 21:53:03218 EXPECT_EQ(gfx::Rect(0, 0, 600, 553 + height_offset).ToString(),
219 maximized->GetWindowBoundsInScreen().ToString());
220 EXPECT_EQ(gfx::Rect(0, 0, 600, 553 + height_offset).ToString(),
[email protected]e2f64d102012-07-19 19:17:04221 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26222
oshima5594d1232015-12-04 18:58:38223 // Set fullscreen to true, but maximized window's size won't change because
224 // it's not visible. see crbug.com/504299.
[email protected]2a64b0a2013-07-23 23:15:54225 fullscreen->SetFullscreen(true);
226 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
tdanderson0b7905b2016-06-22 21:53:03227 EXPECT_EQ(gfx::Rect(0, 0, 600, 553 + height_offset).ToString(),
228 maximized->GetWindowBoundsInScreen().ToString());
229 EXPECT_EQ(gfx::Rect(0, 0, 600, 553 + height_offset).ToString(),
[email protected]2a64b0a2013-07-23 23:15:54230 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
231
[email protected]f1853122012-06-27 16:21:26232 EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow());
jamescookb8dcef522016-06-25 14:42:55233 EXPECT_EQ("400,20 100x100", minimized->GetWindowBoundsInScreen().ToString());
[email protected]f1853122012-06-27 16:21:26234
235 EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow());
236 EXPECT_TRUE(fullscreen->IsFullscreen());
jamescookb8dcef522016-06-25 14:42:55237 EXPECT_EQ("0,0 600x600", fullscreen->GetWindowBoundsInScreen().ToString());
[email protected]8d625fb2012-07-18 16:40:06238 EXPECT_EQ("0,0 600x600",
[email protected]e2f64d102012-07-19 19:17:04239 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8d625fb2012-07-18 16:40:06240
241 // Test if the restore bounds are correctly updated.
[email protected]a41b4e12013-09-20 04:36:34242 wm::GetWindowState(maximized->GetNativeView())->Restore();
[email protected]2816c2462013-12-17 02:22:25243 EXPECT_EQ("200,20 100x100", maximized->GetWindowBoundsInScreen().ToString());
244 EXPECT_EQ("200,20 100x100",
[email protected]e2f64d102012-07-19 19:17:04245 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8d625fb2012-07-18 16:40:06246
247 fullscreen->SetFullscreen(false);
jamescookb8dcef522016-06-25 14:42:55248 EXPECT_EQ("500,20 100x100", fullscreen->GetWindowBoundsInScreen().ToString());
[email protected]2816c2462013-12-17 02:22:25249 EXPECT_EQ("500,20 100x100",
[email protected]e2f64d102012-07-19 19:17:04250 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8f2f151412013-01-26 03:58:37251
252 // Test if the unparented widget has moved.
253 EXPECT_EQ(root_windows[0],
254 unparented_control->GetNativeView()->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28255 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
[email protected]8f2f151412013-01-26 03:58:37256 unparented_control->GetNativeView()->parent()->id());
[email protected]95db9c12013-01-31 11:47:44257
258 // Test if the panel has moved.
259 EXPECT_EQ(root_windows[0], panel->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28260 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
[email protected]f1853122012-06-27 16:21:26261}
262
tdanderson0b7905b2016-06-22 21:53:03263TEST_P(RootWindowControllerTest, MoveWindows_Modal) {
[email protected]e75642a2013-06-12 17:21:18264 if (!SupportsMultipleDisplays())
265 return;
[email protected]1c3f7002013-01-21 18:46:05266
[email protected]f634dd32012-07-23 22:49:07267 UpdateDisplay("500x500,500x500");
[email protected]f1853122012-06-27 16:21:26268
[email protected]c9390bd2013-11-08 20:33:13269 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]f1853122012-06-27 16:21:26270 // Emulate virtual screen coordinate system.
271 root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500));
272 root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500));
273
274 views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100));
275 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
276 EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView()));
277
278 views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100));
279 EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow());
jamescookb8dcef522016-06-25 14:42:55280 EXPECT_TRUE(
281 GetModalContainer(root_windows[1])->Contains(modal->GetNativeView()));
[email protected]f1853122012-06-27 16:21:26282 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
283
[email protected]73c9fd02014-07-28 01:48:52284 ui::test::EventGenerator generator_1st(root_windows[0]);
[email protected]f1853122012-06-27 16:21:26285 generator_1st.ClickLeftButton();
286 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
287
[email protected]f634dd32012-07-23 22:49:07288 UpdateDisplay("500x500");
[email protected]f1853122012-06-27 16:21:26289 EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow());
290 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
291 generator_1st.ClickLeftButton();
292 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
293}
294
oshima022a9542015-05-01 00:15:02295// Make sure lock related windows moves.
tdanderson0b7905b2016-06-22 21:53:03296TEST_P(RootWindowControllerTest, MoveWindows_LockWindowsInUnified) {
oshima022a9542015-05-01 00:15:02297 if (!SupportsMultipleDisplays())
298 return;
oshima628a6172015-08-01 01:33:14299 Shell::GetInstance()->display_manager()->SetUnifiedDesktopEnabled(true);
oshimabba2d992015-05-22 19:21:39300
oshima022a9542015-05-01 00:15:02301 UpdateDisplay("500x500");
302 const int kLockScreenWindowId = 1000;
303 const int kLockBackgroundWindowId = 1001;
304
305 RootWindowController* controller =
306 Shell::GetInstance()->GetPrimaryRootWindowController();
307
308 aura::Window* lock_container =
309 controller->GetContainer(kShellWindowId_LockScreenContainer);
310 aura::Window* lock_background_container =
311 controller->GetContainer(kShellWindowId_LockScreenBackgroundContainer);
312
313 views::Widget* lock_screen =
314 CreateModalWidgetWithParent(gfx::Rect(10, 10, 100, 100), lock_container);
315 lock_screen->GetNativeWindow()->set_id(kLockScreenWindowId);
316 lock_screen->SetFullscreen(true);
317
318 views::Widget* lock_background = CreateModalWidgetWithParent(
319 gfx::Rect(10, 10, 100, 100), lock_background_container);
320 lock_background->GetNativeWindow()->set_id(kLockBackgroundWindowId);
321
322 ASSERT_EQ(lock_screen->GetNativeWindow(),
323 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
324 ASSERT_EQ(lock_background->GetNativeWindow(),
325 controller->GetRootWindow()->GetChildById(kLockBackgroundWindowId));
326 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
327
328 // Switch to unified.
329 UpdateDisplay("500x500,500x500");
330
331 // In unified mode, RWC is created
332 controller = Shell::GetInstance()->GetPrimaryRootWindowController();
333
334 ASSERT_EQ(lock_screen->GetNativeWindow(),
335 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
336 ASSERT_EQ(lock_background->GetNativeWindow(),
337 controller->GetRootWindow()->GetChildById(kLockBackgroundWindowId));
oshima96f6a502015-05-02 08:43:32338 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
oshima022a9542015-05-01 00:15:02339
340 // Switch to mirror.
oshima43436d32015-06-19 02:35:25341 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
oshima022a9542015-05-01 00:15:02342 display_manager->SetMirrorMode(true);
343 EXPECT_TRUE(display_manager->IsInMirrorMode());
344
345 controller = Shell::GetInstance()->GetPrimaryRootWindowController();
346 ASSERT_EQ(lock_screen->GetNativeWindow(),
347 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
348 ASSERT_EQ(lock_background->GetNativeWindow(),
349 controller->GetRootWindow()->GetChildById(kLockBackgroundWindowId));
350 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
351
352 // Switch to unified.
353 display_manager->SetMirrorMode(false);
354 EXPECT_TRUE(display_manager->IsInUnifiedMode());
355
356 controller = Shell::GetInstance()->GetPrimaryRootWindowController();
357
358 ASSERT_EQ(lock_screen->GetNativeWindow(),
359 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
360 ASSERT_EQ(lock_background->GetNativeWindow(),
361 controller->GetRootWindow()->GetChildById(kLockBackgroundWindowId));
oshima96f6a502015-05-02 08:43:32362 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
oshima022a9542015-05-01 00:15:02363
364 // Switch to single display.
365 UpdateDisplay("600x500");
366 EXPECT_FALSE(display_manager->IsInUnifiedMode());
367 EXPECT_FALSE(display_manager->IsInMirrorMode());
368
369 controller = Shell::GetInstance()->GetPrimaryRootWindowController();
370
371 ASSERT_EQ(lock_screen->GetNativeWindow(),
372 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
373 ASSERT_EQ(lock_background->GetNativeWindow(),
374 controller->GetRootWindow()->GetChildById(kLockBackgroundWindowId));
375 EXPECT_EQ("0,0 600x500", lock_screen->GetNativeWindow()->bounds().ToString());
376}
377
tdanderson0b7905b2016-06-22 21:53:03378TEST_P(RootWindowControllerTest, ModalContainer) {
[email protected]8674b312012-10-12 19:02:44379 UpdateDisplay("600x600");
380 Shell* shell = Shell::GetInstance();
jamescook443e42d2016-06-10 21:44:46381 WmShell* wm_shell = WmShell::Get();
[email protected]093b8d642014-04-03 20:59:28382 RootWindowController* controller = shell->GetPrimaryRootWindowController();
skye79274a2016-06-08 05:39:02383 EXPECT_EQ(LoginStatus::USER,
jamescook443e42d2016-06-10 21:44:46384 wm_shell->system_tray_delegate()->GetUserLoginStatus());
[email protected]f5c9dbc2014-04-11 08:13:45385 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28386 ->layout_manager(),
387 controller->GetSystemModalLayoutManager(NULL));
[email protected]8674b312012-10-12 19:02:44388
[email protected]3b162e12012-11-09 11:52:35389 views::Widget* session_modal_widget =
390 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]f5c9dbc2014-04-11 08:13:45391 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28392 ->layout_manager(),
393 controller->GetSystemModalLayoutManager(
394 session_modal_widget->GetNativeView()));
[email protected]3b162e12012-11-09 11:52:35395
[email protected]fcb123d2013-04-17 15:58:49396 shell->session_state_delegate()->LockScreen();
skye79274a2016-06-08 05:39:02397 EXPECT_EQ(LoginStatus::LOCKED,
jamescook443e42d2016-06-10 21:44:46398 wm_shell->system_tray_delegate()->GetUserLoginStatus());
[email protected]f5c9dbc2014-04-11 08:13:45399 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28400 ->layout_manager(),
401 controller->GetSystemModalLayoutManager(NULL));
[email protected]3b162e12012-11-09 11:52:35402
[email protected]f5c9dbc2014-04-11 08:13:45403 aura::Window* lock_container =
404 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]3b162e12012-11-09 11:52:35405 views::Widget* lock_modal_widget =
406 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
[email protected]f5c9dbc2014-04-11 08:13:45407 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28408 ->layout_manager(),
409 controller->GetSystemModalLayoutManager(
410 lock_modal_widget->GetNativeView()));
[email protected]f5c9dbc2014-04-11 08:13:45411 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28412 ->layout_manager(),
[email protected]3b162e12012-11-09 11:52:35413 controller->GetSystemModalLayoutManager(
414 session_modal_widget->GetNativeView()));
415
[email protected]fcb123d2013-04-17 15:58:49416 shell->session_state_delegate()->UnlockScreen();
[email protected]8674b312012-10-12 19:02:44417}
418
tdanderson0b7905b2016-06-22 21:53:03419TEST_P(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
[email protected]1b219922012-11-13 21:16:43420 UpdateDisplay("600x600");
421 Shell* shell = Shell::GetInstance();
jamescook443e42d2016-06-10 21:44:46422 WmShell* wm_shell = WmShell::Get();
[email protected]1b219922012-11-13 21:16:43423
424 // Configure login screen environment.
425 SetUserLoggedIn(false);
skye79274a2016-06-08 05:39:02426 EXPECT_EQ(LoginStatus::NOT_LOGGED_IN,
jamescook443e42d2016-06-10 21:44:46427 wm_shell->system_tray_delegate()->GetUserLoginStatus());
[email protected]c8d19f82013-05-18 09:09:41428 EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers());
[email protected]fcb123d2013-04-17 15:58:49429 EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted());
[email protected]1b219922012-11-13 21:16:43430
[email protected]093b8d642014-04-03 20:59:28431 RootWindowController* controller = shell->GetPrimaryRootWindowController();
[email protected]f5c9dbc2014-04-11 08:13:45432 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28433 ->layout_manager(),
434 controller->GetSystemModalLayoutManager(NULL));
[email protected]1b219922012-11-13 21:16:43435
[email protected]f5c9dbc2014-04-11 08:13:45436 aura::Window* lock_container =
437 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]1b219922012-11-13 21:16:43438 views::Widget* login_modal_widget =
439 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
[email protected]f5c9dbc2014-04-11 08:13:45440 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28441 ->layout_manager(),
442 controller->GetSystemModalLayoutManager(
443 login_modal_widget->GetNativeView()));
[email protected]1b219922012-11-13 21:16:43444 login_modal_widget->Close();
445
446 // Configure user session environment.
447 SetUserLoggedIn(true);
448 SetSessionStarted(true);
skye79274a2016-06-08 05:39:02449 EXPECT_EQ(LoginStatus::USER,
jamescook443e42d2016-06-10 21:44:46450 wm_shell->system_tray_delegate()->GetUserLoginStatus());
[email protected]c8d19f82013-05-18 09:09:41451 EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers());
[email protected]fcb123d2013-04-17 15:58:49452 EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted());
[email protected]f5c9dbc2014-04-11 08:13:45453 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28454 ->layout_manager(),
455 controller->GetSystemModalLayoutManager(NULL));
[email protected]1b219922012-11-13 21:16:43456
457 views::Widget* session_modal_widget =
jamescookb8dcef522016-06-25 14:42:55458 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]f5c9dbc2014-04-11 08:13:45459 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28460 ->layout_manager(),
461 controller->GetSystemModalLayoutManager(
462 session_modal_widget->GetNativeView()));
[email protected]1b219922012-11-13 21:16:43463}
464
tdanderson0b7905b2016-06-22 21:53:03465TEST_P(RootWindowControllerTest, ModalContainerBlockedSession) {
[email protected]a44afbbd2013-07-24 21:49:35466 UpdateDisplay("600x600");
Peter Kastingbe940e92014-11-20 23:14:08467 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
[email protected]f5c9dbc2014-04-11 08:13:45468 aura::Window* lock_container =
469 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]a44afbbd2013-07-24 21:49:35470 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55471 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]a44afbbd2013-07-24 21:49:35472 views::Widget* session_modal_widget =
jamescookb8dcef522016-06-25 14:42:55473 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]f5c9dbc2014-04-11 08:13:45474 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28475 ->layout_manager(),
476 controller->GetSystemModalLayoutManager(
477 session_modal_widget->GetNativeView()));
[email protected]f5c9dbc2014-04-11 08:13:45478 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28479 ->layout_manager(),
480 controller->GetSystemModalLayoutManager(NULL));
[email protected]a44afbbd2013-07-24 21:49:35481 session_modal_widget->Close();
482
483 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
484
[email protected]f5c9dbc2014-04-11 08:13:45485 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28486 ->layout_manager(),
487 controller->GetSystemModalLayoutManager(NULL));
[email protected]a44afbbd2013-07-24 21:49:35488
jamescookb8dcef522016-06-25 14:42:55489 views::Widget* lock_modal_widget = CreateModalWidgetWithParent(
490 gfx::Rect(300, 10, 100, 100), lock_container);
[email protected]f5c9dbc2014-04-11 08:13:45491 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28492 ->layout_manager(),
[email protected]a44afbbd2013-07-24 21:49:35493 controller->GetSystemModalLayoutManager(
494 lock_modal_widget->GetNativeView()));
495
jamescookb8dcef522016-06-25 14:42:55496 session_modal_widget = CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]f5c9dbc2014-04-11 08:13:45497 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
[email protected]093b8d642014-04-03 20:59:28498 ->layout_manager(),
499 controller->GetSystemModalLayoutManager(
500 session_modal_widget->GetNativeView()));
[email protected]a44afbbd2013-07-24 21:49:35501 session_modal_widget->Close();
502
503 lock_modal_widget->Close();
504 UnblockUserSession();
505 }
506}
507
tdanderson0b7905b2016-06-22 21:53:03508TEST_P(RootWindowControllerTest, GetWindowForFullscreenMode) {
[email protected]2ee2f5d2013-01-10 23:37:16509 UpdateDisplay("600x600");
[email protected]093b8d642014-04-03 20:59:28510 RootWindowController* controller =
[email protected]2ee2f5d2013-01-10 23:37:16511 Shell::GetInstance()->GetPrimaryRootWindowController();
512
[email protected]700849f2013-04-30 17:49:20513 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
[email protected]2ee2f5d2013-01-10 23:37:16514 w1->Maximize();
[email protected]700849f2013-04-30 17:49:20515 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
516 w2->SetFullscreen(true);
517 // |w3| is a transient child of |w2|.
jamescookb8dcef522016-06-25 14:42:55518 Widget* w3 = Widget::CreateWindowWithParentAndBounds(
519 NULL, w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
[email protected]2ee2f5d2013-01-10 23:37:16520
[email protected]2c9171d22013-12-10 21:55:10521 // Test that GetWindowForFullscreenMode() finds the fullscreen window when one
[email protected]e3bc88e2013-09-06 06:22:06522 // of its transient children is active.
[email protected]700849f2013-04-30 17:49:20523 w3->Activate();
[email protected]2c9171d22013-12-10 21:55:10524 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
[email protected]2ee2f5d2013-01-10 23:37:16525
[email protected]2c9171d22013-12-10 21:55:10526 // If the topmost window is not fullscreen, it returns NULL.
[email protected]700849f2013-04-30 17:49:20527 w1->Activate();
[email protected]2c9171d22013-12-10 21:55:10528 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
529 w1->Close();
530 w3->Close();
[email protected]e3bc88e2013-09-06 06:22:06531
[email protected]2c9171d22013-12-10 21:55:10532 // Only w2 remains, if minimized GetWindowForFullscreenMode should return
533 // NULL.
[email protected]e3bc88e2013-09-06 06:22:06534 w2->Activate();
[email protected]2c9171d22013-12-10 21:55:10535 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
536 w2->Minimize();
537 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
[email protected]2ee2f5d2013-01-10 23:37:16538}
539
tdanderson0b7905b2016-06-22 21:53:03540TEST_P(RootWindowControllerTest, MultipleDisplaysGetWindowForFullscreenMode) {
[email protected]2c5db9e2014-02-27 13:58:14541 if (!SupportsMultipleDisplays())
542 return;
543
544 UpdateDisplay("600x600,600x600");
545 Shell::RootWindowControllerList controllers =
546 Shell::GetInstance()->GetAllRootWindowControllers();
547
548 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
549 w1->Maximize();
550 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
551 w2->SetFullscreen(true);
552 Widget* w3 = CreateTestWidget(gfx::Rect(600, 0, 100, 100));
553
554 EXPECT_EQ(w1->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45555 controllers[0]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14556 EXPECT_EQ(w2->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45557 controllers[0]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14558 EXPECT_EQ(w3->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45559 controllers[1]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14560
561 w1->Activate();
562 EXPECT_EQ(NULL, controllers[0]->GetWindowForFullscreenMode());
563 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
564
565 w2->Activate();
566 EXPECT_EQ(w2->GetNativeWindow(),
567 controllers[0]->GetWindowForFullscreenMode());
568 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
569
570 // Verify that the first root window controller remains in fullscreen mode
571 // when a window on the other display is activated.
572 w3->Activate();
573 EXPECT_EQ(w2->GetNativeWindow(),
574 controllers[0]->GetWindowForFullscreenMode());
575 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
576}
577
jamescook5d74ac02016-05-12 19:57:12578// Test that GetRootWindowController() works with multiple displays and
579// child widgets.
tdanderson0b7905b2016-06-22 21:53:03580TEST_P(RootWindowControllerTest, GetRootWindowController) {
jamescook5d74ac02016-05-12 19:57:12581 if (!SupportsMultipleDisplays())
582 return;
583 UpdateDisplay("600x600,600x600");
584 Shell::RootWindowControllerList controllers =
585 Shell::GetInstance()->GetAllRootWindowControllers();
586 ASSERT_EQ(2u, controllers.size());
587
588 // Test null.
589 EXPECT_FALSE(GetRootWindowController(nullptr));
590
591 // Test a widget on the first display.
592 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
593 EXPECT_EQ(controllers[0],
594 GetRootWindowController(w1->GetNativeWindow()->GetRootWindow()));
595
596 // Test a child widget.
597 Widget* w2 = Widget::CreateWindowWithParentAndBounds(
598 nullptr, w1->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
599 EXPECT_EQ(controllers[0],
600 GetRootWindowController(w2->GetNativeWindow()->GetRootWindow()));
601
602 // Test a widget on the second display.
603 Widget* w3 = CreateTestWidget(gfx::Rect(600, 0, 100, 100));
604 EXPECT_EQ(controllers[1],
605 GetRootWindowController(w3->GetNativeWindow()->GetRootWindow()));
606}
607
[email protected]82ced2352013-07-19 20:49:06608// Test that user session window can't be focused if user session blocked by
609// some overlapping UI.
tdanderson0b7905b2016-06-22 21:53:03610TEST_P(RootWindowControllerTest, FocusBlockedWindow) {
[email protected]82ced2352013-07-19 20:49:06611 UpdateDisplay("600x600");
[email protected]093b8d642014-04-03 20:59:28612 RootWindowController* controller =
[email protected]82ced2352013-07-19 20:49:06613 Shell::GetInstance()->GetPrimaryRootWindowController();
[email protected]f5c9dbc2014-04-11 08:13:45614 aura::Window* lock_container =
615 controller->GetContainer(kShellWindowId_LockScreenContainer);
jamescookb8dcef522016-06-25 14:42:55616 aura::Window* lock_window =
617 Widget::CreateWindowWithParentAndBounds(NULL, lock_container,
618 gfx::Rect(0, 0, 100, 100))
619 ->GetNativeView();
[email protected]82ced2352013-07-19 20:49:06620 lock_window->Show();
621 aura::Window* session_window =
622 CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView();
623 session_window->Show();
624
[email protected]a44afbbd2013-07-24 21:49:35625 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55626 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]a44afbbd2013-07-24 21:49:35627 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
628 lock_window->Focus();
629 EXPECT_TRUE(lock_window->HasFocus());
630 session_window->Focus();
631 EXPECT_FALSE(session_window->HasFocus());
632 UnblockUserSession();
633 }
[email protected]82ced2352013-07-19 20:49:06634}
635
[email protected]0fbfa972013-10-02 19:23:33636// Tracks whether OnWindowDestroying() has been invoked.
637class DestroyedWindowObserver : public aura::WindowObserver {
638 public:
639 DestroyedWindowObserver() : destroyed_(false), window_(NULL) {}
dcheng1f4538e2014-10-27 23:57:05640 ~DestroyedWindowObserver() override { Shutdown(); }
[email protected]0fbfa972013-10-02 19:23:33641
642 void SetWindow(Window* window) {
643 window_ = window;
644 window->AddObserver(this);
645 }
646
647 bool destroyed() const { return destroyed_; }
648
649 // WindowObserver overrides:
dcheng1f4538e2014-10-27 23:57:05650 void OnWindowDestroying(Window* window) override {
[email protected]0fbfa972013-10-02 19:23:33651 destroyed_ = true;
652 Shutdown();
653 }
654
655 private:
656 void Shutdown() {
657 if (!window_)
658 return;
659 window_->RemoveObserver(this);
660 window_ = NULL;
661 }
662
663 bool destroyed_;
664 Window* window_;
665
666 DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver);
667};
668
669// Verifies shutdown doesn't delete windows that are not owned by the parent.
tdanderson0b7905b2016-06-22 21:53:03670TEST_P(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) {
[email protected]0fbfa972013-10-02 19:23:33671 DestroyedWindowObserver observer1;
672 aura::test::TestWindowDelegate delegate1;
673 aura::Window* window1 = new aura::Window(&delegate1);
[email protected]5b251f12013-12-19 01:50:05674 window1->SetType(ui::wm::WINDOW_TYPE_CONTROL);
[email protected]0fbfa972013-10-02 19:23:33675 window1->set_owned_by_parent(false);
676 observer1.SetWindow(window1);
danakjb161836d2015-04-03 05:14:18677 window1->Init(ui::LAYER_NOT_DRAWN);
[email protected]e3225e02013-10-23 20:44:37678 aura::client::ParentWindowWithContext(
679 window1, Shell::GetInstance()->GetPrimaryRootWindow(), gfx::Rect());
[email protected]0fbfa972013-10-02 19:23:33680
681 DestroyedWindowObserver observer2;
682 aura::Window* window2 = new aura::Window(NULL);
683 window2->set_owned_by_parent(false);
684 observer2.SetWindow(window2);
danakjb161836d2015-04-03 05:14:18685 window2->Init(ui::LAYER_NOT_DRAWN);
[email protected]0fbfa972013-10-02 19:23:33686 Shell::GetInstance()->GetPrimaryRootWindow()->AddChild(window2);
687
688 Shell::GetInstance()->GetPrimaryRootWindowController()->CloseChildWindows();
689
690 ASSERT_FALSE(observer1.destroyed());
691 delete window1;
692
693 ASSERT_FALSE(observer2.destroyed());
694 delete window2;
695}
696
[email protected]cf6fea22013-08-07 14:24:01697typedef test::NoSessionAshTestBase NoSessionRootWindowControllerTest;
698
699// Make sure that an event handler exists for entire display area.
700TEST_F(NoSessionRootWindowControllerTest, Event) {
[email protected]bf9cdb362013-10-25 19:22:45701 aura::Window* root = Shell::GetPrimaryRootWindow();
[email protected]cf6fea22013-08-07 14:24:01702 const gfx::Size size = root->bounds().size();
mswf9da4d82016-04-07 18:19:35703 EXPECT_TRUE(root->GetEventHandlerForPoint(gfx::Point(0, 0)));
704 EXPECT_TRUE(root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
705 EXPECT_TRUE(root->GetEventHandlerForPoint(gfx::Point(size.width() - 1, 0)));
706 EXPECT_TRUE(root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
707 EXPECT_TRUE(root->GetEventHandlerForPoint(
708 gfx::Point(size.width() - 1, size.height() - 1)));
[email protected]cf6fea22013-08-07 14:24:01709}
710
[email protected]24f5e242014-07-22 02:16:09711class VirtualKeyboardRootWindowControllerTest
712 : public RootWindowControllerTest {
[email protected]eff4c7f2013-08-13 01:45:50713 public:
dcheng1f4538e2014-10-27 23:57:05714 VirtualKeyboardRootWindowControllerTest() {}
715 ~VirtualKeyboardRootWindowControllerTest() override {}
[email protected]eff4c7f2013-08-13 01:45:50716
dcheng1f4538e2014-10-27 23:57:05717 void SetUp() override {
pgal.u-szegedd84534d32014-10-29 12:34:30718 base::CommandLine::ForCurrentProcess()->AppendSwitch(
[email protected]eff4c7f2013-08-13 01:45:50719 keyboard::switches::kEnableVirtualKeyboard);
720 test::AshTestBase::SetUp();
[email protected]24ca45d2013-10-25 03:37:44721 Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
[email protected]a0b3fb882014-04-07 19:26:03722 keyboard::KeyboardController::GetInstance());
[email protected]eff4c7f2013-08-13 01:45:50723 }
724
725 private:
726 DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest);
727};
728
[email protected]2082d7d2014-05-13 14:44:23729class MockTextInputClient : public ui::DummyTextInputClient {
730 public:
jamescookb8dcef522016-06-25 14:42:55731 MockTextInputClient() : ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {}
[email protected]2082d7d2014-05-13 14:44:23732
dcheng1f4538e2014-10-27 23:57:05733 void EnsureCaretInRect(const gfx::Rect& rect) override {
[email protected]2082d7d2014-05-13 14:44:23734 visible_rect_ = rect;
735 }
736
jamescookb8dcef522016-06-25 14:42:55737 const gfx::Rect& visible_rect() const { return visible_rect_; }
[email protected]2082d7d2014-05-13 14:44:23738
739 private:
740 gfx::Rect visible_rect_;
741
742 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
743};
744
kevers23f3987d2014-09-17 13:50:12745class TargetHitTestEventHandler : public ui::test::TestEventHandler {
746 public:
747 TargetHitTestEventHandler() {}
748
749 // ui::test::TestEventHandler overrides.
dcheng1f4538e2014-10-27 23:57:05750 void OnMouseEvent(ui::MouseEvent* event) override {
kevers23f3987d2014-09-17 13:50:12751 if (event->type() == ui::ET_MOUSE_PRESSED)
752 ui::test::TestEventHandler::OnMouseEvent(event);
753 event->StopPropagation();
754 }
755
756 private:
757 DISALLOW_COPY_AND_ASSIGN(TargetHitTestEventHandler);
758};
759
[email protected]b6ba05d902013-10-04 21:38:45760// Test for http://crbug.com/297858. Virtual keyboard container should only show
761// on primary root window.
762TEST_F(VirtualKeyboardRootWindowControllerTest,
763 VirtualKeyboardOnPrimaryRootWindowOnly) {
764 if (!SupportsMultipleDisplays())
765 return;
766
767 UpdateDisplay("500x500,500x500");
768
[email protected]c9390bd2013-11-08 20:33:13769 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]bf9cdb362013-10-25 19:22:45770 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
jamescookb8dcef522016-06-25 14:42:55771 aura::Window* secondary_root_window = root_windows[0] == primary_root_window
772 ? root_windows[1]
773 : root_windows[0];
[email protected]b6ba05d902013-10-04 21:38:45774
[email protected]093b8d642014-04-03 20:59:28775 ASSERT_TRUE(Shell::GetContainer(primary_root_window,
776 kShellWindowId_VirtualKeyboardContainer));
777 ASSERT_FALSE(Shell::GetContainer(secondary_root_window,
778 kShellWindowId_VirtualKeyboardContainer));
[email protected]b6ba05d902013-10-04 21:38:45779}
780
[email protected]eff4c7f2013-08-13 01:45:50781// Test for http://crbug.com/263599. Virtual keyboard should be able to receive
782// events at blocked user session.
783TEST_F(VirtualKeyboardRootWindowControllerTest,
784 ClickVirtualKeyboardInBlockedWindow) {
[email protected]bf9cdb362013-10-25 19:22:45785 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28786 aura::Window* keyboard_container =
787 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]eff4c7f2013-08-13 01:45:50788 ASSERT_TRUE(keyboard_container);
789 keyboard_container->Show();
790
ben974286a2015-10-10 00:45:12791 aura::Window* keyboard_window =
792 keyboard::KeyboardController::GetInstance()->ui()->GetKeyboardWindow();
[email protected]647b4842013-12-12 14:24:24793 keyboard_container->AddChild(keyboard_window);
[email protected]183e28d2014-01-20 18:18:02794 keyboard_window->set_owned_by_parent(false);
[email protected]647b4842013-12-12 14:24:24795 keyboard_window->SetBounds(gfx::Rect());
[email protected]eff4c7f2013-08-13 01:45:50796 keyboard_window->Show();
[email protected]647b4842013-12-12 14:24:24797
[email protected]3193ea722014-04-23 22:19:19798 ui::test::TestEventHandler handler;
799 root_window->AddPreTargetHandler(&handler);
[email protected]647b4842013-12-12 14:24:24800
[email protected]73c9fd02014-07-28 01:48:52801 ui::test::EventGenerator event_generator(root_window, keyboard_window);
[email protected]eff4c7f2013-08-13 01:45:50802 event_generator.ClickLeftButton();
803 int expected_mouse_presses = 1;
[email protected]3193ea722014-04-23 22:19:19804 EXPECT_EQ(expected_mouse_presses, handler.num_mouse_events() / 2);
[email protected]eff4c7f2013-08-13 01:45:50805
806 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55807 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]eff4c7f2013-08-13 01:45:50808 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
809 event_generator.ClickLeftButton();
810 expected_mouse_presses++;
[email protected]3193ea722014-04-23 22:19:19811 EXPECT_EQ(expected_mouse_presses, handler.num_mouse_events() / 2);
[email protected]eff4c7f2013-08-13 01:45:50812 UnblockUserSession();
813 }
[email protected]3193ea722014-04-23 22:19:19814 root_window->RemovePreTargetHandler(&handler);
[email protected]eff4c7f2013-08-13 01:45:50815}
816
[email protected]45c66672013-10-01 22:48:56817// Test for http://crbug.com/299787. RootWindowController should delete
818// the old container since the keyboard controller creates a new window in
819// GetWindowContainer().
820TEST_F(VirtualKeyboardRootWindowControllerTest,
821 DeleteOldContainerOnVirtualKeyboardInit) {
[email protected]1025937e2014-02-13 01:25:50822 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28823 aura::Window* keyboard_container =
824 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]45c66672013-10-01 22:48:56825 ASSERT_TRUE(keyboard_container);
826 // Track the keyboard container window.
827 aura::WindowTracker tracker;
828 tracker.Add(keyboard_container);
[email protected]51f438112013-11-18 19:32:50829 // Mock a login user profile change to reinitialize the keyboard.
830 ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
[email protected]45c66672013-10-01 22:48:56831 // keyboard_container should no longer be present.
832 EXPECT_FALSE(tracker.Contains(keyboard_container));
833}
834
[email protected]1025937e2014-02-13 01:25:50835// Test for crbug.com/342524. After user login, the work space should restore to
836// full screen.
837TEST_F(VirtualKeyboardRootWindowControllerTest, RestoreWorkspaceAfterLogin) {
838 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28839 aura::Window* keyboard_container =
840 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]1025937e2014-02-13 01:25:50841 keyboard_container->Show();
842 keyboard::KeyboardController* controller =
[email protected]a0b3fb882014-04-07 19:26:03843 keyboard::KeyboardController::GetInstance();
ben974286a2015-10-10 00:45:12844 aura::Window* keyboard_window = controller->ui()->GetKeyboardWindow();
[email protected]1025937e2014-02-13 01:25:50845 keyboard_container->AddChild(keyboard_window);
846 keyboard_window->set_owned_by_parent(false);
bshea0a57802015-04-08 18:21:29847 keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
848 root_window->bounds(), 100));
[email protected]1025937e2014-02-13 01:25:50849 keyboard_window->Show();
850
oshimaf84b0da722016-04-27 19:47:19851 gfx::Rect before =
852 display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
[email protected]1025937e2014-02-13 01:25:50853
854 // Notify keyboard bounds changing.
bshea0a57802015-04-08 18:21:29855 controller->NotifyKeyboardBoundsChanging(keyboard_container->bounds());
[email protected]1025937e2014-02-13 01:25:50856
[email protected]25df7ad2014-04-30 18:10:25857 if (!keyboard::IsKeyboardOverscrollEnabled()) {
oshimaf84b0da722016-04-27 19:47:19858 gfx::Rect after =
859 display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
[email protected]25df7ad2014-04-30 18:10:25860 EXPECT_LT(after, before);
861 }
[email protected]1025937e2014-02-13 01:25:50862
863 // Mock a login user profile change to reinitialize the keyboard.
864 ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
oshimaf84b0da722016-04-27 19:47:19865 EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().work_area(),
866 before);
[email protected]1025937e2014-02-13 01:25:50867}
868
[email protected]602022b2014-03-31 17:07:31869// Ensure that system modal dialogs do not block events targeted at the virtual
870// keyboard.
871TEST_F(VirtualKeyboardRootWindowControllerTest, ClickWithActiveModalDialog) {
872 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28873 aura::Window* keyboard_container =
874 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]602022b2014-03-31 17:07:31875 ASSERT_TRUE(keyboard_container);
876 keyboard_container->Show();
877
ben974286a2015-10-10 00:45:12878 aura::Window* keyboard_window =
879 keyboard::KeyboardController::GetInstance()->ui()->GetKeyboardWindow();
[email protected]602022b2014-03-31 17:07:31880 keyboard_container->AddChild(keyboard_window);
881 keyboard_window->set_owned_by_parent(false);
bshea0a57802015-04-08 18:21:29882 keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
883 root_window->bounds(), 100));
[email protected]3193ea722014-04-23 22:19:19884
885 ui::test::TestEventHandler handler;
886 root_window->AddPreTargetHandler(&handler);
[email protected]73c9fd02014-07-28 01:48:52887 ui::test::EventGenerator root_window_event_generator(root_window);
888 ui::test::EventGenerator keyboard_event_generator(root_window,
889 keyboard_window);
[email protected]602022b2014-03-31 17:07:31890
jamescookb8dcef522016-06-25 14:42:55891 views::Widget* modal_widget = CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]602022b2014-03-31 17:07:31892
893 // Verify that mouse events to the root window are block with a visble modal
894 // dialog.
895 root_window_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:19896 EXPECT_EQ(0, handler.num_mouse_events());
[email protected]602022b2014-03-31 17:07:31897
898 // Verify that event dispatch to the virtual keyboard is unblocked.
899 keyboard_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:19900 EXPECT_EQ(1, handler.num_mouse_events() / 2);
[email protected]602022b2014-03-31 17:07:31901
902 modal_widget->Close();
903
904 // Verify that mouse events are now unblocked to the root window.
905 root_window_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:19906 EXPECT_EQ(2, handler.num_mouse_events() / 2);
907 root_window->RemovePreTargetHandler(&handler);
[email protected]602022b2014-03-31 17:07:31908}
909
[email protected]2082d7d2014-05-13 14:44:23910// Ensure that the visible area for scrolling the text caret excludes the
911// region occluded by the on-screen keyboard.
912TEST_F(VirtualKeyboardRootWindowControllerTest, EnsureCaretInWorkArea) {
913 keyboard::KeyboardController* keyboard_controller =
914 keyboard::KeyboardController::GetInstance();
ben974286a2015-10-10 00:45:12915 keyboard::KeyboardUI* ui = keyboard_controller->ui();
[email protected]2082d7d2014-05-13 14:44:23916
917 MockTextInputClient text_input_client;
ben974286a2015-10-10 00:45:12918 ui::InputMethod* input_method = ui->GetInputMethod();
[email protected]2082d7d2014-05-13 14:44:23919 ASSERT_TRUE(input_method);
shuchen4e09795a2015-06-15 15:07:20920 input_method->SetFocusedTextInputClient(&text_input_client);
[email protected]2082d7d2014-05-13 14:44:23921
922 aura::Window* root_window = Shell::GetPrimaryRootWindow();
923 aura::Window* keyboard_container =
924 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
925 ASSERT_TRUE(keyboard_container);
926 keyboard_container->Show();
927
928 const int keyboard_height = 100;
ben974286a2015-10-10 00:45:12929 aura::Window* keyboard_window = ui->GetKeyboardWindow();
[email protected]2082d7d2014-05-13 14:44:23930 keyboard_container->AddChild(keyboard_window);
931 keyboard_window->set_owned_by_parent(false);
bshea0a57802015-04-08 18:21:29932 keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
933 root_window->bounds(), keyboard_height));
[email protected]2082d7d2014-05-13 14:44:23934
ben974286a2015-10-10 00:45:12935 ui->EnsureCaretInWorkArea();
bshea0a57802015-04-08 18:21:29936 ASSERT_EQ(root_window->bounds().width(),
[email protected]2082d7d2014-05-13 14:44:23937 text_input_client.visible_rect().width());
bshea0a57802015-04-08 18:21:29938 ASSERT_EQ(root_window->bounds().height() - keyboard_height,
[email protected]2082d7d2014-05-13 14:44:23939 text_input_client.visible_rect().height());
[email protected]00a386792014-06-16 15:09:20940
shuchen4e09795a2015-06-15 15:07:20941 input_method->SetFocusedTextInputClient(NULL);
[email protected]2082d7d2014-05-13 14:44:23942}
943
kevers23f3987d2014-09-17 13:50:12944// Tests that the virtual keyboard does not block context menus. The virtual
945// keyboard should appear in front of most content, but not context menus. See
946// crbug/377180.
947TEST_F(VirtualKeyboardRootWindowControllerTest, ZOrderTest) {
948 UpdateDisplay("800x600");
949 keyboard::KeyboardController* keyboard_controller =
950 keyboard::KeyboardController::GetInstance();
ben974286a2015-10-10 00:45:12951 keyboard::KeyboardUI* ui = keyboard_controller->ui();
kevers23f3987d2014-09-17 13:50:12952
953 aura::Window* root_window = Shell::GetPrimaryRootWindow();
954 aura::Window* keyboard_container =
955 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
956 ASSERT_TRUE(keyboard_container);
957 keyboard_container->Show();
958
959 const int keyboard_height = 200;
ben974286a2015-10-10 00:45:12960 aura::Window* keyboard_window = ui->GetKeyboardWindow();
kevers23f3987d2014-09-17 13:50:12961 keyboard_container->AddChild(keyboard_window);
962 keyboard_window->set_owned_by_parent(false);
bshea0a57802015-04-08 18:21:29963 gfx::Rect keyboard_bounds = keyboard::FullWidthKeyboardBoundsFromRootBounds(
964 root_window->bounds(), keyboard_height);
kevers23f3987d2014-09-17 13:50:12965 keyboard_window->SetBounds(keyboard_bounds);
966 keyboard_window->Show();
967
968 ui::test::EventGenerator generator(root_window);
969
970 // Cover the screen with two windows: a normal window on the left side and a
971 // context menu on the right side. When the virtual keyboard is displayed it
972 // partially occludes the normal window, but not the context menu. Compute
973 // positions for generating synthetic click events to perform hit tests,
974 // ensuring the correct window layering. 'top' is above the VK, whereas
975 // 'bottom' lies within the VK. 'left' is centered in the normal window, and
976 // 'right' is centered in the context menu.
977 int window_height = keyboard_bounds.bottom();
978 int window_width = keyboard_bounds.width() / 2;
979 int left = window_width / 2;
980 int right = 3 * window_width / 2;
981 int top = keyboard_bounds.y() / 2;
982 int bottom = window_height - keyboard_height / 2;
983
984 // Normal window is partially occluded by the virtual keyboard.
985 aura::test::TestWindowDelegate delegate;
dchenga94547472016-04-08 08:41:11986 std::unique_ptr<aura::Window> normal(
987 CreateTestWindowInShellWithDelegateAndType(
988 &delegate, ui::wm::WINDOW_TYPE_NORMAL, 0,
989 gfx::Rect(0, 0, window_width, window_height)));
kevers23f3987d2014-09-17 13:50:12990 normal->set_owned_by_parent(false);
991 normal->Show();
992 TargetHitTestEventHandler normal_handler;
993 normal->AddPreTargetHandler(&normal_handler);
994
995 // Test that only the click on the top portion of the window is picked up. The
996 // click on the bottom hits the virtual keyboard instead.
997 generator.MoveMouseTo(left, top);
998 generator.ClickLeftButton();
999 EXPECT_EQ(1, normal_handler.num_mouse_events());
1000 generator.MoveMouseTo(left, bottom);
1001 generator.ClickLeftButton();
1002 EXPECT_EQ(1, normal_handler.num_mouse_events());
1003
1004 // Menu overlaps virtual keyboard.
1005 aura::test::TestWindowDelegate delegate2;
dchenga94547472016-04-08 08:41:111006 std::unique_ptr<aura::Window> menu(CreateTestWindowInShellWithDelegateAndType(
1007 &delegate2, ui::wm::WINDOW_TYPE_MENU, 0,
kevers23f3987d2014-09-17 13:50:121008 gfx::Rect(window_width, 0, window_width, window_height)));
1009 menu->set_owned_by_parent(false);
1010 menu->Show();
1011 TargetHitTestEventHandler menu_handler;
1012 menu->AddPreTargetHandler(&menu_handler);
1013
1014 // Test that both clicks register.
1015 generator.MoveMouseTo(right, top);
1016 generator.ClickLeftButton();
1017 EXPECT_EQ(1, menu_handler.num_mouse_events());
1018 generator.MoveMouseTo(right, bottom);
1019 generator.ClickLeftButton();
1020 EXPECT_EQ(2, menu_handler.num_mouse_events());
1021
1022 // Cleanup to ensure that the test windows are destroyed before their
1023 // delegates.
1024 normal.reset();
1025 menu.reset();
1026}
1027
kevers0e450492014-09-30 16:02:311028// Resolution in UpdateDisplay is not being respected on Windows 8.
1029#if defined(OS_WIN)
1030#define MAYBE_DisplayRotation DISABLED_DisplayRotation
1031#else
1032#define MAYBE_DisplayRotation DisplayRotation
1033#endif
1034
1035// Tests that the virtual keyboard correctly resizes with a change to display
1036// orientation. See crbug/417612.
1037TEST_F(VirtualKeyboardRootWindowControllerTest, MAYBE_DisplayRotation) {
1038 UpdateDisplay("800x600");
1039 aura::Window* root_window = Shell::GetPrimaryRootWindow();
1040 aura::Window* keyboard_container =
1041 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
1042 ASSERT_TRUE(keyboard_container);
bshea0a57802015-04-08 18:21:291043 keyboard::KeyboardController* keyboard_controller =
1044 keyboard::KeyboardController::GetInstance();
1045 keyboard_controller->ShowKeyboard(false);
ben974286a2015-10-10 00:45:121046 keyboard_controller->ui()->GetKeyboardWindow()->SetBounds(
bshea0a57802015-04-08 18:21:291047 gfx::Rect(0, 400, 800, 200));
1048 EXPECT_EQ("0,400 800x200", keyboard_container->bounds().ToString());
kevers0e450492014-09-30 16:02:311049
1050 UpdateDisplay("600x800");
bshea0a57802015-04-08 18:21:291051 EXPECT_EQ("0,600 600x200", keyboard_container->bounds().ToString());
kevers0e450492014-09-30 16:02:311052}
1053
[email protected]f1853122012-06-27 16:21:261054} // namespace test
1055} // namespace ash