blob: 6695dbbeeef2ef4952112e0f7253420c69b14018 [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
skye5fd1222017-04-12 18:43:239#include "ash/public/cpp/config.h"
jamescook8800b8232016-10-19 12:46:2710#include "ash/public/cpp/shell_window_ids.h"
James Cookb0bf8e82017-04-09 17:01:4411#include "ash/session/session_controller.h"
[email protected]f1853122012-06-27 16:21:2612#include "ash/shell.h"
[email protected]f1853122012-06-27 16:21:2613#include "ash/test/ash_test_base.h"
James Cookb0bf8e82017-04-09 17:01:4414#include "ash/test/test_session_controller_client.h"
15#include "ash/wm/system_modal_container_layout_manager.h"
[email protected]2ee2f5d2013-01-10 23:37:1616#include "ash/wm/window_properties.h"
James Cookb0bf8e82017-04-09 17:01:4417#include "ash/wm/window_state.h"
[email protected]f1853122012-06-27 16:21:2618#include "ash/wm/window_util.h"
[email protected]eff4c7f2013-08-13 01:45:5019#include "base/command_line.h"
[email protected]792b9b12012-12-11 03:53:2720#include "ui/aura/client/focus_change_observer.h"
[email protected]8cfb6722012-11-28 03:28:4621#include "ui/aura/client/focus_client.h"
sky28f20d62016-10-20 23:21:5922#include "ui/aura/client/window_parenting_client.h"
[email protected]f1853122012-06-27 16:21:2623#include "ui/aura/env.h"
[email protected]dbf835d82012-09-11 18:23:0924#include "ui/aura/test/test_window_delegate.h"
25#include "ui/aura/test/test_windows.h"
[email protected]f1853122012-06-27 16:21:2626#include "ui/aura/window.h"
[email protected]fcc51c952014-02-21 21:31:2627#include "ui/aura/window_event_dispatcher.h"
[email protected]dbf835d82012-09-11 18:23:0928#include "ui/aura/window_tracker.h"
[email protected]2082d7d2014-05-13 14:44:2329#include "ui/base/ime/dummy_text_input_client.h"
30#include "ui/base/ime/input_method.h"
31#include "ui/base/ime/text_input_client.h"
rjkroege72f8154f2016-10-29 00:49:0232#include "ui/display/manager/display_manager.h"
yhanada7e20c9b12016-11-25 00:03:1933#include "ui/display/test/display_manager_test_api.h"
34#include "ui/events/devices/device_data_manager.h"
35#include "ui/events/devices/touchscreen_device.h"
[email protected]73c9fd02014-07-28 01:48:5236#include "ui/events/test/event_generator.h"
[email protected]cd9f71d2014-03-20 21:54:2137#include "ui/events/test/test_event_handler.h"
jamescookcf8b648f2016-06-01 19:58:1738#include "ui/keyboard/keyboard_controller.h"
[email protected]eff4c7f2013-08-13 01:45:5039#include "ui/keyboard/keyboard_switches.h"
ben974286a2015-10-10 00:45:1240#include "ui/keyboard/keyboard_ui.h"
[email protected]39e95212014-04-23 20:00:0141#include "ui/keyboard/keyboard_util.h"
[email protected]f1853122012-06-27 16:21:2642#include "ui/views/controls/menu/menu_controller.h"
43#include "ui/views/widget/widget.h"
44#include "ui/views/widget/widget_delegate.h"
45
[email protected]2ee2f5d2013-01-10 23:37:1646using aura::Window;
47using views::Widget;
48
[email protected]f1853122012-06-27 16:21:2649namespace ash {
50namespace {
51
52class TestDelegate : public views::WidgetDelegateView {
53 public:
54 explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {}
dcheng1f4538e2014-10-27 23:57:0555 ~TestDelegate() override {}
[email protected]f1853122012-06-27 16:21:2656
57 // Overridden from views::WidgetDelegate:
dcheng1f4538e2014-10-27 23:57:0558 ui::ModalType GetModalType() const override {
[email protected]f1853122012-06-27 16:21:2659 return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
60 }
61
62 private:
63 bool system_modal_;
[email protected]0fbfa972013-10-02 19:23:3364
[email protected]f1853122012-06-27 16:21:2665 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
66};
67
[email protected]792b9b12012-12-11 03:53:2768class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate,
69 public aura::client::FocusChangeObserver {
[email protected]dbf835d82012-09-11 18:23:0970 public:
71 DeleteOnBlurDelegate() : window_(NULL) {}
dcheng1f4538e2014-10-27 23:57:0572 ~DeleteOnBlurDelegate() override {}
[email protected]dbf835d82012-09-11 18:23:0973
[email protected]792b9b12012-12-11 03:53:2774 void SetWindow(aura::Window* window) {
75 window_ = window;
76 aura::client::SetFocusChangeObserver(window_, this);
77 }
[email protected]dbf835d82012-09-11 18:23:0978
[email protected]869f6352012-12-06 20:47:1779 private:
[email protected]dbf835d82012-09-11 18:23:0980 // aura::test::TestWindowDelegate overrides:
dcheng1f4538e2014-10-27 23:57:0581 bool CanFocus() override { return true; }
[email protected]dbf835d82012-09-11 18:23:0982
[email protected]792b9b12012-12-11 03:53:2783 // aura::client::FocusChangeObserver implementation:
dcheng1f4538e2014-10-27 23:57:0584 void OnWindowFocused(aura::Window* gained_focus,
85 aura::Window* lost_focus) override {
[email protected]792b9b12012-12-11 03:53:2786 if (window_ == lost_focus)
87 delete window_;
[email protected]869f6352012-12-06 20:47:1788 }
89
[email protected]dbf835d82012-09-11 18:23:0990 aura::Window* window_;
91
92 DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate);
93};
94
sky97f9a7432017-05-09 05:14:3195aura::LayoutManager* GetLayoutManager(RootWindowController* controller,
96 int id) {
97 return controller->GetContainer(id)->layout_manager();
skyb6643832017-01-11 22:08:4598}
99
[email protected]f1853122012-06-27 16:21:26100} // namespace
101
102namespace test {
[email protected]f1853122012-06-27 16:21:26103
estadea23d6ceb2017-02-15 00:47:09104class RootWindowControllerTest : public AshTestBase {
[email protected]a2e6af12013-01-07 21:40:35105 public:
106 views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
107 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
108 NULL, CurrentContext(), bounds);
109 widget->Show();
110 return widget;
111 }
112
113 views::Widget* CreateModalWidget(const gfx::Rect& bounds) {
114 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
115 new TestDelegate(true), CurrentContext(), bounds);
116 widget->Show();
117 return widget;
118 }
119
120 views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds,
121 gfx::NativeWindow parent) {
jamescookb8dcef522016-06-25 14:42:55122 views::Widget* widget = views::Widget::CreateWindowWithParentAndBounds(
123 new TestDelegate(true), parent, bounds);
[email protected]a2e6af12013-01-07 21:40:35124 widget->Show();
125 return widget;
126 }
127
[email protected]c9390bd2013-11-08 20:33:13128 aura::Window* GetModalContainer(aura::Window* root_window) {
[email protected]093b8d642014-04-03 20:59:28129 return Shell::GetContainer(root_window,
mswbc0a8b482016-06-30 02:21:14130 kShellWindowId_SystemModalContainer);
[email protected]a2e6af12013-01-07 21:40:35131 }
132};
[email protected]f1853122012-06-27 16:21:26133
estadea23d6ceb2017-02-15 00:47:09134TEST_F(RootWindowControllerTest, MoveWindows_Basic) {
[email protected]2816c2462013-12-17 02:22:25135 // Windows origin should be doubled when moved to the 1st display.
136 UpdateDisplay("600x600,300x300");
[email protected]c9390bd2013-11-08 20:33:13137 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]f1853122012-06-27 16:21:26138
139 views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100));
140 EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow());
[email protected]e2f64d102012-07-19 19:17:04141 EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString());
[email protected]8d625fb2012-07-18 16:40:06142 EXPECT_EQ("50,10 100x100",
[email protected]e2f64d102012-07-19 19:17:04143 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26144
145 views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100));
146 maximized->Maximize();
147 EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow());
estadea23d6ceb2017-02-15 00:47:09148 EXPECT_EQ(gfx::Rect(600, 0, 300, 252).ToString(),
tdanderson0b7905b2016-06-22 21:53:03149 maximized->GetWindowBoundsInScreen().ToString());
estadea23d6ceb2017-02-15 00:47:09150 EXPECT_EQ(gfx::Rect(0, 0, 300, 252).ToString(),
[email protected]8c0ec432013-05-10 04:33:39151 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26152
oshima92224ac2017-02-22 06:27:43153 views::Widget* minimized = CreateTestWidget(gfx::Rect(550, 10, 200, 200));
[email protected]f1853122012-06-27 16:21:26154 minimized->Minimize();
155 EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow());
oshima92224ac2017-02-22 06:27:43156 EXPECT_EQ("550,10 200x200", minimized->GetWindowBoundsInScreen().ToString());
[email protected]f1853122012-06-27 16:21:26157
oshima92224ac2017-02-22 06:27:43158 views::Widget* fullscreen = CreateTestWidget(gfx::Rect(850, 10, 200, 200));
sky56ce72b72017-02-27 19:07:06159 display::Display secondary_display = GetSecondaryDisplay();
oshima92224ac2017-02-22 06:27:43160 gfx::Rect orig_bounds = fullscreen->GetWindowBoundsInScreen();
161 EXPECT_TRUE(secondary_display.work_area().Intersects(orig_bounds));
162 EXPECT_FALSE(secondary_display.work_area().Contains(orig_bounds));
163
[email protected]f1853122012-06-27 16:21:26164 fullscreen->SetFullscreen(true);
165 EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow());
[email protected]1a015382012-12-01 19:44:59166
jamescookb8dcef522016-06-25 14:42:55167 EXPECT_EQ("600,0 300x300", fullscreen->GetWindowBoundsInScreen().ToString());
[email protected]2816c2462013-12-17 02:22:25168 EXPECT_EQ("0,0 300x300",
[email protected]e2f64d102012-07-19 19:17:04169 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26170
[email protected]8f2f151412013-01-26 03:58:37171 views::Widget* unparented_control = new Widget;
172 Widget::InitParams params;
173 params.bounds = gfx::Rect(650, 10, 100, 100);
174 params.context = CurrentContext();
175 params.type = Widget::InitParams::TYPE_CONTROL;
176 unparented_control->Init(params);
177 EXPECT_EQ(root_windows[1],
178 unparented_control->GetNativeView()->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28179 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
[email protected]8f2f151412013-01-26 03:58:37180 unparented_control->GetNativeView()->parent()->id());
181
[email protected]95db9c12013-01-31 11:47:44182 aura::Window* panel = CreateTestWindowInShellWithDelegateAndType(
Thiago Farina627fba952017-05-24 21:15:26183 NULL, aura::client::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100));
[email protected]95db9c12013-01-31 11:47:44184 EXPECT_EQ(root_windows[1], panel->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28185 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
[email protected]95db9c12013-01-31 11:47:44186
skye5fd1222017-04-12 18:43:23187 if (Shell::GetAshConfig() == Config::MASH) {
erg2ee938282017-03-01 00:41:48188 // TODO(erg): Ignore this one part of the test when running mash. We would
189 // crash because the aura::Window |d2| created in the other block doesn't
190 // get deleted, and thus continues to contain a reference to its delegate,
191 // |delete_on_blur_delegate|, which is declared on the stack.
192 //
193 // Making this work requires building out enough of the display management
194 // system; notably the part where updating the display may cause focus
195 // changes. http://crbug.com/695632.
196 UpdateDisplay("600x600");
197 } else {
198 // Make sure a window that will delete itself when losing focus
199 // will not crash.
200 aura::WindowTracker tracker;
201 DeleteOnBlurDelegate delete_on_blur_delegate;
202 aura::Window* d2 = CreateTestWindowInShellWithDelegate(
203 &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100));
204 delete_on_blur_delegate.SetWindow(d2);
205 aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2);
206 tracker.Add(d2);
[email protected]dbf835d82012-09-11 18:23:09207
erg2ee938282017-03-01 00:41:48208 UpdateDisplay("600x600");
[email protected]f1853122012-06-27 16:21:26209
erg2ee938282017-03-01 00:41:48210 // d2 must have been deleted.
211 EXPECT_FALSE(tracker.Contains(d2));
212 }
[email protected]dbf835d82012-09-11 18:23:09213
[email protected]f1853122012-06-27 16:21:26214 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
[email protected]2816c2462013-12-17 02:22:25215 EXPECT_EQ("100,20 100x100", normal->GetWindowBoundsInScreen().ToString());
216 EXPECT_EQ("100,20 100x100",
[email protected]e2f64d102012-07-19 19:17:04217 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26218
estade29fc92d2017-04-20 04:24:46219 // Maximized area on primary display has 48px for inset at the bottom
220 // (kShelfSize).
[email protected]2a64b0a2013-07-23 23:15:54221
222 // First clear fullscreen status, since both fullscreen and maximized windows
223 // share the same desktop workspace, which cancels the shelf status.
224 fullscreen->SetFullscreen(false);
[email protected]f1853122012-06-27 16:21:26225 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
estadea23d6ceb2017-02-15 00:47:09226 EXPECT_EQ(gfx::Rect(0, 0, 600, 552).ToString(),
tdanderson0b7905b2016-06-22 21:53:03227 maximized->GetWindowBoundsInScreen().ToString());
estadea23d6ceb2017-02-15 00:47:09228 EXPECT_EQ(gfx::Rect(0, 0, 600, 552).ToString(),
[email protected]e2f64d102012-07-19 19:17:04229 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]f1853122012-06-27 16:21:26230
oshima5594d1232015-12-04 18:58:38231 // Set fullscreen to true, but maximized window's size won't change because
232 // it's not visible. see crbug.com/504299.
[email protected]2a64b0a2013-07-23 23:15:54233 fullscreen->SetFullscreen(true);
234 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
estadea23d6ceb2017-02-15 00:47:09235 EXPECT_EQ(gfx::Rect(0, 0, 600, 552).ToString(),
tdanderson0b7905b2016-06-22 21:53:03236 maximized->GetWindowBoundsInScreen().ToString());
estadea23d6ceb2017-02-15 00:47:09237 EXPECT_EQ(gfx::Rect(0, 0, 600, 552).ToString(),
[email protected]2a64b0a2013-07-23 23:15:54238 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
239
[email protected]f1853122012-06-27 16:21:26240 EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow());
oshima92224ac2017-02-22 06:27:43241 EXPECT_EQ("0,20 200x200", minimized->GetWindowBoundsInScreen().ToString());
[email protected]f1853122012-06-27 16:21:26242
243 EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow());
244 EXPECT_TRUE(fullscreen->IsFullscreen());
jamescookb8dcef522016-06-25 14:42:55245 EXPECT_EQ("0,0 600x600", fullscreen->GetWindowBoundsInScreen().ToString());
[email protected]8d625fb2012-07-18 16:40:06246 EXPECT_EQ("0,0 600x600",
[email protected]e2f64d102012-07-19 19:17:04247 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8d625fb2012-07-18 16:40:06248
249 // Test if the restore bounds are correctly updated.
[email protected]a41b4e12013-09-20 04:36:34250 wm::GetWindowState(maximized->GetNativeView())->Restore();
[email protected]2816c2462013-12-17 02:22:25251 EXPECT_EQ("200,20 100x100", maximized->GetWindowBoundsInScreen().ToString());
252 EXPECT_EQ("200,20 100x100",
[email protected]e2f64d102012-07-19 19:17:04253 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8d625fb2012-07-18 16:40:06254
255 fullscreen->SetFullscreen(false);
oshima92224ac2017-02-22 06:27:43256 EXPECT_EQ("400,20 200x200", fullscreen->GetWindowBoundsInScreen().ToString());
257 EXPECT_EQ("400,20 200x200",
[email protected]e2f64d102012-07-19 19:17:04258 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
[email protected]8f2f151412013-01-26 03:58:37259
260 // Test if the unparented widget has moved.
261 EXPECT_EQ(root_windows[0],
262 unparented_control->GetNativeView()->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28263 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
[email protected]8f2f151412013-01-26 03:58:37264 unparented_control->GetNativeView()->parent()->id());
[email protected]95db9c12013-01-31 11:47:44265
266 // Test if the panel has moved.
267 EXPECT_EQ(root_windows[0], panel->GetRootWindow());
[email protected]093b8d642014-04-03 20:59:28268 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
[email protected]f1853122012-06-27 16:21:26269}
270
estadea23d6ceb2017-02-15 00:47:09271TEST_F(RootWindowControllerTest, MoveWindows_Modal) {
[email protected]f634dd32012-07-23 22:49:07272 UpdateDisplay("500x500,500x500");
[email protected]f1853122012-06-27 16:21:26273
[email protected]c9390bd2013-11-08 20:33:13274 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]f1853122012-06-27 16:21:26275 // Emulate virtual screen coordinate system.
276 root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500));
277 root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500));
278
279 views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100));
280 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
281 EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView()));
282
283 views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100));
284 EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow());
jamescookb8dcef522016-06-25 14:42:55285 EXPECT_TRUE(
286 GetModalContainer(root_windows[1])->Contains(modal->GetNativeView()));
[email protected]f1853122012-06-27 16:21:26287 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
288
[email protected]73c9fd02014-07-28 01:48:52289 ui::test::EventGenerator generator_1st(root_windows[0]);
[email protected]f1853122012-06-27 16:21:26290 generator_1st.ClickLeftButton();
291 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
292
[email protected]f634dd32012-07-23 22:49:07293 UpdateDisplay("500x500");
[email protected]f1853122012-06-27 16:21:26294 EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow());
295 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
296 generator_1st.ClickLeftButton();
297 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
298}
299
oshima022a9542015-05-01 00:15:02300// Make sure lock related windows moves.
estadea23d6ceb2017-02-15 00:47:09301TEST_F(RootWindowControllerTest, MoveWindows_LockWindowsInUnified) {
sky56ce72b72017-02-27 19:07:06302 // TODO: requires unified desktop mode. http://crbug.com/581462.
skye5fd1222017-04-12 18:43:23303 if (Shell::GetAshConfig() == Config::MASH)
sky56ce72b72017-02-27 19:07:06304 return;
305
rjkroege72f8154f2016-10-29 00:49:02306 display_manager()->SetUnifiedDesktopEnabled(true);
oshimabba2d992015-05-22 19:21:39307
oshima022a9542015-05-01 00:15:02308 UpdateDisplay("500x500");
309 const int kLockScreenWindowId = 1000;
msw607227f82016-08-30 17:22:39310 const int kLockWallpaperWindowId = 1001;
oshima022a9542015-05-01 00:15:02311
mswbc0a8b482016-06-30 02:21:14312 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
oshima022a9542015-05-01 00:15:02313
314 aura::Window* lock_container =
315 controller->GetContainer(kShellWindowId_LockScreenContainer);
msw607227f82016-08-30 17:22:39316 aura::Window* lock_wallpaper_container =
317 controller->GetContainer(kShellWindowId_LockScreenWallpaperContainer);
oshima022a9542015-05-01 00:15:02318
319 views::Widget* lock_screen =
320 CreateModalWidgetWithParent(gfx::Rect(10, 10, 100, 100), lock_container);
321 lock_screen->GetNativeWindow()->set_id(kLockScreenWindowId);
322 lock_screen->SetFullscreen(true);
323
msw607227f82016-08-30 17:22:39324 views::Widget* lock_wallpaper = CreateModalWidgetWithParent(
325 gfx::Rect(10, 10, 100, 100), lock_wallpaper_container);
326 lock_wallpaper->GetNativeWindow()->set_id(kLockWallpaperWindowId);
oshima022a9542015-05-01 00:15:02327
328 ASSERT_EQ(lock_screen->GetNativeWindow(),
329 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
msw607227f82016-08-30 17:22:39330 ASSERT_EQ(lock_wallpaper->GetNativeWindow(),
331 controller->GetRootWindow()->GetChildById(kLockWallpaperWindowId));
oshima022a9542015-05-01 00:15:02332 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
333
334 // Switch to unified.
335 UpdateDisplay("500x500,500x500");
336
337 // In unified mode, RWC is created
mswbc0a8b482016-06-30 02:21:14338 controller = Shell::GetPrimaryRootWindowController();
oshima022a9542015-05-01 00:15:02339
340 ASSERT_EQ(lock_screen->GetNativeWindow(),
341 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
msw607227f82016-08-30 17:22:39342 ASSERT_EQ(lock_wallpaper->GetNativeWindow(),
343 controller->GetRootWindow()->GetChildById(kLockWallpaperWindowId));
oshima96f6a502015-05-02 08:43:32344 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
oshima022a9542015-05-01 00:15:02345
346 // Switch to mirror.
rjkroege72f8154f2016-10-29 00:49:02347 display_manager()->SetMirrorMode(true);
348 EXPECT_TRUE(display_manager()->IsInMirrorMode());
oshima022a9542015-05-01 00:15:02349
mswbc0a8b482016-06-30 02:21:14350 controller = Shell::GetPrimaryRootWindowController();
oshima022a9542015-05-01 00:15:02351 ASSERT_EQ(lock_screen->GetNativeWindow(),
352 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
msw607227f82016-08-30 17:22:39353 ASSERT_EQ(lock_wallpaper->GetNativeWindow(),
354 controller->GetRootWindow()->GetChildById(kLockWallpaperWindowId));
oshima022a9542015-05-01 00:15:02355 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
356
357 // Switch to unified.
rjkroege72f8154f2016-10-29 00:49:02358 display_manager()->SetMirrorMode(false);
359 EXPECT_TRUE(display_manager()->IsInUnifiedMode());
oshima022a9542015-05-01 00:15:02360
mswbc0a8b482016-06-30 02:21:14361 controller = Shell::GetPrimaryRootWindowController();
oshima022a9542015-05-01 00:15:02362
363 ASSERT_EQ(lock_screen->GetNativeWindow(),
364 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
msw607227f82016-08-30 17:22:39365 ASSERT_EQ(lock_wallpaper->GetNativeWindow(),
366 controller->GetRootWindow()->GetChildById(kLockWallpaperWindowId));
oshima96f6a502015-05-02 08:43:32367 EXPECT_EQ("0,0 500x500", lock_screen->GetNativeWindow()->bounds().ToString());
oshima022a9542015-05-01 00:15:02368
369 // Switch to single display.
370 UpdateDisplay("600x500");
rjkroege72f8154f2016-10-29 00:49:02371 EXPECT_FALSE(display_manager()->IsInUnifiedMode());
372 EXPECT_FALSE(display_manager()->IsInMirrorMode());
oshima022a9542015-05-01 00:15:02373
mswbc0a8b482016-06-30 02:21:14374 controller = Shell::GetPrimaryRootWindowController();
oshima022a9542015-05-01 00:15:02375
376 ASSERT_EQ(lock_screen->GetNativeWindow(),
377 controller->GetRootWindow()->GetChildById(kLockScreenWindowId));
msw607227f82016-08-30 17:22:39378 ASSERT_EQ(lock_wallpaper->GetNativeWindow(),
379 controller->GetRootWindow()->GetChildById(kLockWallpaperWindowId));
oshima022a9542015-05-01 00:15:02380 EXPECT_EQ("0,0 600x500", lock_screen->GetNativeWindow()->bounds().ToString());
381}
382
estadea23d6ceb2017-02-15 00:47:09383TEST_F(RootWindowControllerTest, ModalContainer) {
[email protected]8674b312012-10-12 19:02:44384 UpdateDisplay("600x600");
mswad3d9552017-05-18 21:23:36385 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
xiyuan6779a042017-05-05 21:27:55386 EXPECT_TRUE(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
skyb6643832017-01-11 22:08:45387 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28388 controller->GetSystemModalLayoutManager(NULL));
[email protected]8674b312012-10-12 19:02:44389
[email protected]3b162e12012-11-09 11:52:35390 views::Widget* session_modal_widget =
391 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
skyb6643832017-01-11 22:08:45392 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28393 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31394 session_modal_widget->GetNativeWindow()));
[email protected]3b162e12012-11-09 11:52:35395
sky5ad143a2017-03-22 04:31:23396 Shell::Get()->session_controller()->LockScreenAndFlushForTest();
xiyuan6779a042017-05-05 21:27:55397 EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
skyb6643832017-01-11 22:08:45398 EXPECT_EQ(
399 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
400 controller->GetSystemModalLayoutManager(nullptr));
[email protected]3b162e12012-11-09 11:52:35401
skyb6643832017-01-11 22:08:45402 aura::Window* lock_container =
403 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]3b162e12012-11-09 11:52:35404 views::Widget* lock_modal_widget =
405 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
skyb6643832017-01-11 22:08:45406 EXPECT_EQ(
407 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
408 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31409 lock_modal_widget->GetNativeWindow()));
skyb6643832017-01-11 22:08:45410 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]3b162e12012-11-09 11:52:35411 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31412 session_modal_widget->GetNativeWindow()));
[email protected]3b162e12012-11-09 11:52:35413
xiyuanf1ff14d2017-03-20 20:28:14414 GetSessionControllerClient()->UnlockScreen();
[email protected]8674b312012-10-12 19:02:44415}
416
estadea23d6ceb2017-02-15 00:47:09417TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
[email protected]1b219922012-11-13 21:16:43418 UpdateDisplay("600x600");
[email protected]1b219922012-11-13 21:16:43419
420 // Configure login screen environment.
sky5ad143a2017-03-22 04:31:23421 SessionController* session_controller = Shell::Get()->session_controller();
[email protected]1b219922012-11-13 21:16:43422 SetUserLoggedIn(false);
xiyuanf1ff14d2017-03-20 20:28:14423 EXPECT_EQ(0, session_controller->NumberOfLoggedInUsers());
424 EXPECT_FALSE(session_controller->IsActiveUserSessionStarted());
[email protected]1b219922012-11-13 21:16:43425
mswad3d9552017-05-18 21:23:36426 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
skyb6643832017-01-11 22:08:45427 EXPECT_EQ(
428 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
429 controller->GetSystemModalLayoutManager(NULL));
[email protected]1b219922012-11-13 21:16:43430
skyb6643832017-01-11 22:08:45431 aura::Window* lock_container =
432 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]1b219922012-11-13 21:16:43433 views::Widget* login_modal_widget =
434 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
skyb6643832017-01-11 22:08:45435 EXPECT_EQ(
436 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
437 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31438 login_modal_widget->GetNativeWindow()));
[email protected]1b219922012-11-13 21:16:43439 login_modal_widget->Close();
440
441 // Configure user session environment.
442 SetUserLoggedIn(true);
443 SetSessionStarted(true);
xiyuanf1ff14d2017-03-20 20:28:14444 EXPECT_EQ(1, session_controller->NumberOfLoggedInUsers());
445 EXPECT_TRUE(session_controller->IsActiveUserSessionStarted());
skyb6643832017-01-11 22:08:45446 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28447 controller->GetSystemModalLayoutManager(NULL));
[email protected]1b219922012-11-13 21:16:43448
449 views::Widget* session_modal_widget =
jamescookb8dcef522016-06-25 14:42:55450 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
skyb6643832017-01-11 22:08:45451 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28452 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31453 session_modal_widget->GetNativeWindow()));
[email protected]1b219922012-11-13 21:16:43454}
455
estadea23d6ceb2017-02-15 00:47:09456TEST_F(RootWindowControllerTest, ModalContainerBlockedSession) {
[email protected]a44afbbd2013-07-24 21:49:35457 UpdateDisplay("600x600");
mswad3d9552017-05-18 21:23:36458 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
skyb6643832017-01-11 22:08:45459 aura::Window* lock_container =
460 controller->GetContainer(kShellWindowId_LockScreenContainer);
[email protected]a44afbbd2013-07-24 21:49:35461 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55462 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]a44afbbd2013-07-24 21:49:35463 views::Widget* session_modal_widget =
jamescookb8dcef522016-06-25 14:42:55464 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
skyb6643832017-01-11 22:08:45465 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28466 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31467 session_modal_widget->GetNativeWindow()));
skyb6643832017-01-11 22:08:45468 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28469 controller->GetSystemModalLayoutManager(NULL));
[email protected]a44afbbd2013-07-24 21:49:35470 session_modal_widget->Close();
471
472 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
473
skyb6643832017-01-11 22:08:45474 EXPECT_EQ(
475 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
476 controller->GetSystemModalLayoutManager(NULL));
[email protected]a44afbbd2013-07-24 21:49:35477
jamescookb8dcef522016-06-25 14:42:55478 views::Widget* lock_modal_widget = CreateModalWidgetWithParent(
479 gfx::Rect(300, 10, 100, 100), lock_container);
skyb6643832017-01-11 22:08:45480 EXPECT_EQ(
481 GetLayoutManager(controller, kShellWindowId_LockSystemModalContainer),
482 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31483 lock_modal_widget->GetNativeWindow()));
[email protected]a44afbbd2013-07-24 21:49:35484
jamescookb8dcef522016-06-25 14:42:55485 session_modal_widget = CreateModalWidget(gfx::Rect(300, 10, 100, 100));
skyb6643832017-01-11 22:08:45486 EXPECT_EQ(GetLayoutManager(controller, kShellWindowId_SystemModalContainer),
[email protected]093b8d642014-04-03 20:59:28487 controller->GetSystemModalLayoutManager(
sky97f9a7432017-05-09 05:14:31488 session_modal_widget->GetNativeWindow()));
[email protected]a44afbbd2013-07-24 21:49:35489 session_modal_widget->Close();
490
491 lock_modal_widget->Close();
492 UnblockUserSession();
493 }
494}
495
estadea23d6ceb2017-02-15 00:47:09496TEST_F(RootWindowControllerTest, GetWindowForFullscreenMode) {
[email protected]2ee2f5d2013-01-10 23:37:16497 UpdateDisplay("600x600");
mswbc0a8b482016-06-30 02:21:14498 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
[email protected]2ee2f5d2013-01-10 23:37:16499
[email protected]700849f2013-04-30 17:49:20500 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
[email protected]2ee2f5d2013-01-10 23:37:16501 w1->Maximize();
[email protected]700849f2013-04-30 17:49:20502 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
503 w2->SetFullscreen(true);
504 // |w3| is a transient child of |w2|.
jamescookb8dcef522016-06-25 14:42:55505 Widget* w3 = Widget::CreateWindowWithParentAndBounds(
506 NULL, w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
[email protected]2ee2f5d2013-01-10 23:37:16507
[email protected]2c9171d22013-12-10 21:55:10508 // Test that GetWindowForFullscreenMode() finds the fullscreen window when one
[email protected]e3bc88e2013-09-06 06:22:06509 // of its transient children is active.
[email protected]700849f2013-04-30 17:49:20510 w3->Activate();
[email protected]2c9171d22013-12-10 21:55:10511 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
[email protected]2ee2f5d2013-01-10 23:37:16512
[email protected]2c9171d22013-12-10 21:55:10513 // If the topmost window is not fullscreen, it returns NULL.
[email protected]700849f2013-04-30 17:49:20514 w1->Activate();
[email protected]2c9171d22013-12-10 21:55:10515 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
516 w1->Close();
517 w3->Close();
[email protected]e3bc88e2013-09-06 06:22:06518
[email protected]2c9171d22013-12-10 21:55:10519 // Only w2 remains, if minimized GetWindowForFullscreenMode should return
520 // NULL.
[email protected]e3bc88e2013-09-06 06:22:06521 w2->Activate();
[email protected]2c9171d22013-12-10 21:55:10522 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
523 w2->Minimize();
524 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
[email protected]2ee2f5d2013-01-10 23:37:16525}
526
estadea23d6ceb2017-02-15 00:47:09527TEST_F(RootWindowControllerTest, MultipleDisplaysGetWindowForFullscreenMode) {
[email protected]2c5db9e2014-02-27 13:58:14528 UpdateDisplay("600x600,600x600");
529 Shell::RootWindowControllerList controllers =
skycb4be5b2017-04-06 17:52:45530 Shell::Get()->GetAllRootWindowControllers();
[email protected]2c5db9e2014-02-27 13:58:14531
532 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
533 w1->Maximize();
534 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
535 w2->SetFullscreen(true);
536 Widget* w3 = CreateTestWidget(gfx::Rect(600, 0, 100, 100));
537
538 EXPECT_EQ(w1->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45539 controllers[0]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14540 EXPECT_EQ(w2->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45541 controllers[0]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14542 EXPECT_EQ(w3->GetNativeWindow()->GetRootWindow(),
[email protected]f5c9dbc2014-04-11 08:13:45543 controllers[1]->GetRootWindow());
[email protected]2c5db9e2014-02-27 13:58:14544
545 w1->Activate();
546 EXPECT_EQ(NULL, controllers[0]->GetWindowForFullscreenMode());
547 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
548
549 w2->Activate();
550 EXPECT_EQ(w2->GetNativeWindow(),
551 controllers[0]->GetWindowForFullscreenMode());
552 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
553
554 // Verify that the first root window controller remains in fullscreen mode
555 // when a window on the other display is activated.
556 w3->Activate();
557 EXPECT_EQ(w2->GetNativeWindow(),
558 controllers[0]->GetWindowForFullscreenMode());
559 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
560}
561
msw257a6a232017-06-01 01:46:30562// Test that ForWindow() works with multiple displays and child widgets.
563TEST_F(RootWindowControllerTest, ForWindow) {
jamescook5d74ac02016-05-12 19:57:12564 UpdateDisplay("600x600,600x600");
565 Shell::RootWindowControllerList controllers =
skycb4be5b2017-04-06 17:52:45566 Shell::Get()->GetAllRootWindowControllers();
jamescook5d74ac02016-05-12 19:57:12567 ASSERT_EQ(2u, controllers.size());
568
msw257a6a232017-06-01 01:46:30569 // Test a root window.
570 EXPECT_EQ(controllers[0],
571 RootWindowController::ForWindow(Shell::GetPrimaryRootWindow()));
jamescook5d74ac02016-05-12 19:57:12572
573 // Test a widget on the first display.
574 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
575 EXPECT_EQ(controllers[0],
msw257a6a232017-06-01 01:46:30576 RootWindowController::ForWindow(w1->GetNativeWindow()));
jamescook5d74ac02016-05-12 19:57:12577
578 // Test a child widget.
579 Widget* w2 = Widget::CreateWindowWithParentAndBounds(
580 nullptr, w1->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
581 EXPECT_EQ(controllers[0],
msw257a6a232017-06-01 01:46:30582 RootWindowController::ForWindow(w2->GetNativeWindow()));
jamescook5d74ac02016-05-12 19:57:12583
584 // Test a widget on the second display.
585 Widget* w3 = CreateTestWidget(gfx::Rect(600, 0, 100, 100));
586 EXPECT_EQ(controllers[1],
msw257a6a232017-06-01 01:46:30587 RootWindowController::ForWindow(w3->GetNativeWindow()));
jamescook5d74ac02016-05-12 19:57:12588}
589
[email protected]82ced2352013-07-19 20:49:06590// Test that user session window can't be focused if user session blocked by
591// some overlapping UI.
estadea23d6ceb2017-02-15 00:47:09592TEST_F(RootWindowControllerTest, FocusBlockedWindow) {
[email protected]82ced2352013-07-19 20:49:06593 UpdateDisplay("600x600");
mswbc0a8b482016-06-30 02:21:14594 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
[email protected]f5c9dbc2014-04-11 08:13:45595 aura::Window* lock_container =
596 controller->GetContainer(kShellWindowId_LockScreenContainer);
jamescookb8dcef522016-06-25 14:42:55597 aura::Window* lock_window =
598 Widget::CreateWindowWithParentAndBounds(NULL, lock_container,
599 gfx::Rect(0, 0, 100, 100))
600 ->GetNativeView();
[email protected]82ced2352013-07-19 20:49:06601 lock_window->Show();
602 aura::Window* session_window =
603 CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView();
604 session_window->Show();
605
[email protected]a44afbbd2013-07-24 21:49:35606 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55607 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]a44afbbd2013-07-24 21:49:35608 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
609 lock_window->Focus();
610 EXPECT_TRUE(lock_window->HasFocus());
611 session_window->Focus();
612 EXPECT_FALSE(session_window->HasFocus());
613 UnblockUserSession();
614 }
[email protected]82ced2352013-07-19 20:49:06615}
616
[email protected]0fbfa972013-10-02 19:23:33617// Tracks whether OnWindowDestroying() has been invoked.
618class DestroyedWindowObserver : public aura::WindowObserver {
619 public:
620 DestroyedWindowObserver() : destroyed_(false), window_(NULL) {}
dcheng1f4538e2014-10-27 23:57:05621 ~DestroyedWindowObserver() override { Shutdown(); }
[email protected]0fbfa972013-10-02 19:23:33622
623 void SetWindow(Window* window) {
624 window_ = window;
625 window->AddObserver(this);
626 }
627
628 bool destroyed() const { return destroyed_; }
629
630 // WindowObserver overrides:
dcheng1f4538e2014-10-27 23:57:05631 void OnWindowDestroying(Window* window) override {
[email protected]0fbfa972013-10-02 19:23:33632 destroyed_ = true;
633 Shutdown();
634 }
635
636 private:
637 void Shutdown() {
638 if (!window_)
639 return;
640 window_->RemoveObserver(this);
641 window_ = NULL;
642 }
643
644 bool destroyed_;
645 Window* window_;
646
647 DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver);
648};
649
650// Verifies shutdown doesn't delete windows that are not owned by the parent.
estadea23d6ceb2017-02-15 00:47:09651TEST_F(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) {
[email protected]0fbfa972013-10-02 19:23:33652 DestroyedWindowObserver observer1;
653 aura::test::TestWindowDelegate delegate1;
654 aura::Window* window1 = new aura::Window(&delegate1);
Thiago Farina627fba952017-05-24 21:15:26655 window1->SetType(aura::client::WINDOW_TYPE_CONTROL);
[email protected]0fbfa972013-10-02 19:23:33656 window1->set_owned_by_parent(false);
657 observer1.SetWindow(window1);
danakjb161836d2015-04-03 05:14:18658 window1->Init(ui::LAYER_NOT_DRAWN);
msw257a6a232017-06-01 01:46:30659 aura::client::ParentWindowWithContext(window1, Shell::GetPrimaryRootWindow(),
660 gfx::Rect());
[email protected]0fbfa972013-10-02 19:23:33661
662 DestroyedWindowObserver observer2;
663 aura::Window* window2 = new aura::Window(NULL);
664 window2->set_owned_by_parent(false);
665 observer2.SetWindow(window2);
danakjb161836d2015-04-03 05:14:18666 window2->Init(ui::LAYER_NOT_DRAWN);
msw257a6a232017-06-01 01:46:30667 Shell::GetPrimaryRootWindow()->AddChild(window2);
[email protected]0fbfa972013-10-02 19:23:33668
mswbc0a8b482016-06-30 02:21:14669 Shell::GetPrimaryRootWindowController()->CloseChildWindows();
[email protected]0fbfa972013-10-02 19:23:33670
671 ASSERT_FALSE(observer1.destroyed());
672 delete window1;
673
674 ASSERT_FALSE(observer2.destroyed());
675 delete window2;
676}
677
[email protected]24f5e242014-07-22 02:16:09678class VirtualKeyboardRootWindowControllerTest
679 : public RootWindowControllerTest {
[email protected]eff4c7f2013-08-13 01:45:50680 public:
dcheng1f4538e2014-10-27 23:57:05681 VirtualKeyboardRootWindowControllerTest() {}
682 ~VirtualKeyboardRootWindowControllerTest() override {}
[email protected]eff4c7f2013-08-13 01:45:50683
dcheng1f4538e2014-10-27 23:57:05684 void SetUp() override {
pgal.u-szegedd84534d32014-10-29 12:34:30685 base::CommandLine::ForCurrentProcess()->AppendSwitch(
[email protected]eff4c7f2013-08-13 01:45:50686 keyboard::switches::kEnableVirtualKeyboard);
687 test::AshTestBase::SetUp();
yhanada7e20c9b12016-11-25 00:03:19688 keyboard::SetTouchKeyboardEnabled(true);
skycb4be5b2017-04-06 17:52:45689 Shell::Get()->CreateKeyboard();
yhanada7e20c9b12016-11-25 00:03:19690 }
691
692 void TearDown() override {
693 keyboard::SetTouchKeyboardEnabled(false);
694 test::AshTestBase::TearDown();
[email protected]eff4c7f2013-08-13 01:45:50695 }
696
697 private:
698 DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest);
699};
700
[email protected]2082d7d2014-05-13 14:44:23701class MockTextInputClient : public ui::DummyTextInputClient {
702 public:
jamescookb8dcef522016-06-25 14:42:55703 MockTextInputClient() : ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {}
[email protected]2082d7d2014-05-13 14:44:23704
yhanada0ddd3462016-12-08 05:04:18705 void EnsureCaretNotInRect(const gfx::Rect& rect) override {
706 caret_exclude_rect_ = rect;
[email protected]2082d7d2014-05-13 14:44:23707 }
708
yhanada0ddd3462016-12-08 05:04:18709 const gfx::Rect& caret_exclude_rect() const { return caret_exclude_rect_; }
[email protected]2082d7d2014-05-13 14:44:23710
711 private:
yhanada0ddd3462016-12-08 05:04:18712 gfx::Rect caret_exclude_rect_;
[email protected]2082d7d2014-05-13 14:44:23713
714 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
715};
716
kevers23f3987d2014-09-17 13:50:12717class TargetHitTestEventHandler : public ui::test::TestEventHandler {
718 public:
719 TargetHitTestEventHandler() {}
720
721 // ui::test::TestEventHandler overrides.
dcheng1f4538e2014-10-27 23:57:05722 void OnMouseEvent(ui::MouseEvent* event) override {
kevers23f3987d2014-09-17 13:50:12723 if (event->type() == ui::ET_MOUSE_PRESSED)
724 ui::test::TestEventHandler::OnMouseEvent(event);
725 event->StopPropagation();
726 }
727
728 private:
729 DISALLOW_COPY_AND_ASSIGN(TargetHitTestEventHandler);
730};
731
[email protected]b6ba05d902013-10-04 21:38:45732// Test for http://crbug.com/297858. Virtual keyboard container should only show
yhanada7e20c9b12016-11-25 00:03:19733// on primary root window if no window has touch capability.
[email protected]b6ba05d902013-10-04 21:38:45734TEST_F(VirtualKeyboardRootWindowControllerTest,
yhanada7e20c9b12016-11-25 00:03:19735 VirtualKeyboardOnPrimaryRootWindowDefault) {
[email protected]b6ba05d902013-10-04 21:38:45736 UpdateDisplay("500x500,500x500");
737
[email protected]c9390bd2013-11-08 20:33:13738 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
[email protected]bf9cdb362013-10-25 19:22:45739 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
jamescookb8dcef522016-06-25 14:42:55740 aura::Window* secondary_root_window = root_windows[0] == primary_root_window
741 ? root_windows[1]
742 : root_windows[0];
[email protected]b6ba05d902013-10-04 21:38:45743
[email protected]093b8d642014-04-03 20:59:28744 ASSERT_TRUE(Shell::GetContainer(primary_root_window,
745 kShellWindowId_VirtualKeyboardContainer));
746 ASSERT_FALSE(Shell::GetContainer(secondary_root_window,
747 kShellWindowId_VirtualKeyboardContainer));
[email protected]b6ba05d902013-10-04 21:38:45748}
749
yhanada7e20c9b12016-11-25 00:03:19750// Test for http://crbug.com/303429. Virtual keyboard container should show on
751// a display which has touch capability.
752TEST_F(VirtualKeyboardRootWindowControllerTest,
753 VirtualKeyboardOnTouchableDisplayOnly) {
sky56ce72b72017-02-27 19:07:06754 // TODO: investigate failure in mash. http://crbug.com/695640.
skye5fd1222017-04-12 18:43:23755 if (Shell::GetAshConfig() == Config::MASH)
sky56ce72b72017-02-27 19:07:06756 return;
757
yhanada7e20c9b12016-11-25 00:03:19758 UpdateDisplay("500x500,500x500");
759 display::Display secondary_display =
skycb4be5b2017-04-06 17:52:45760 Shell::Get()->display_manager()->GetSecondaryDisplay();
761 display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
yhanada7e20c9b12016-11-25 00:03:19762 .SetTouchSupport(secondary_display.id(),
763 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE);
764
765 // The primary display doesn't have touch capability and the secondary display
766 // does.
767 ASSERT_NE(display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE,
768 display::Screen::GetScreen()->GetPrimaryDisplay().touch_support());
skycb4be5b2017-04-06 17:52:45769 ASSERT_EQ(
770 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE,
771 Shell::Get()->display_manager()->GetSecondaryDisplay().touch_support());
yhanada7e20c9b12016-11-25 00:03:19772
773 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
774 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
775 aura::Window* secondary_root_window = root_windows[0] == primary_root_window
776 ? root_windows[1]
777 : root_windows[0];
778
779 keyboard::KeyboardController::GetInstance()->ShowKeyboard(false);
780 ASSERT_FALSE(Shell::GetContainer(primary_root_window,
781 kShellWindowId_VirtualKeyboardContainer));
782 ASSERT_TRUE(Shell::GetContainer(secondary_root_window,
783 kShellWindowId_VirtualKeyboardContainer));
784
785 // Move the focus to the primary display.
786 aura::Window* focusable_window_in_primary_display =
787 CreateTestWindowInShellWithBounds(
788 primary_root_window->GetBoundsInScreen());
789 ASSERT_EQ(primary_root_window,
790 focusable_window_in_primary_display->GetRootWindow());
791 focusable_window_in_primary_display->Focus();
792 ASSERT_TRUE(focusable_window_in_primary_display->HasFocus());
793
794 // Virtual keyboard shows up on the secondary display even if a window in the
795 // primary screen has the focus.
796 keyboard::KeyboardController::GetInstance()->ShowKeyboard(false);
797 EXPECT_FALSE(Shell::GetContainer(primary_root_window,
798 kShellWindowId_VirtualKeyboardContainer));
799 EXPECT_TRUE(Shell::GetContainer(secondary_root_window,
800 kShellWindowId_VirtualKeyboardContainer));
801}
802
803// Test for http://crbug.com/303429. If both of displays have touch capability,
804// virtual keyboard follows the input focus.
805TEST_F(VirtualKeyboardRootWindowControllerTest, FollowInputFocus) {
sky56ce72b72017-02-27 19:07:06806 // TODO: investigate failure in mash. http://crbug.com/695640.
skye5fd1222017-04-12 18:43:23807 if (Shell::GetAshConfig() == Config::MASH)
sky56ce72b72017-02-27 19:07:06808 return;
809
yhanada7e20c9b12016-11-25 00:03:19810 UpdateDisplay("500x500,500x500");
811 const int64_t primary_display_id =
812 display::Screen::GetScreen()->GetPrimaryDisplay().id();
skycb4be5b2017-04-06 17:52:45813 display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
yhanada7e20c9b12016-11-25 00:03:19814 .SetTouchSupport(primary_display_id,
815 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE);
816 const int64_t secondary_display_id =
skycb4be5b2017-04-06 17:52:45817 Shell::Get()->display_manager()->GetSecondaryDisplay().id();
818 display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
yhanada7e20c9b12016-11-25 00:03:19819 .SetTouchSupport(secondary_display_id,
820 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE);
821
822 // Both of displays have touch capability.
823 ASSERT_EQ(display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE,
824 display::Screen::GetScreen()->GetPrimaryDisplay().touch_support());
skycb4be5b2017-04-06 17:52:45825 ASSERT_EQ(
826 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE,
827 Shell::Get()->display_manager()->GetSecondaryDisplay().touch_support());
yhanada7e20c9b12016-11-25 00:03:19828
829 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
830 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
831 aura::Window* secondary_root_window = root_windows[0] == primary_root_window
832 ? root_windows[1]
833 : root_windows[0];
834 aura::Window* focusable_window_in_primary_display =
835 CreateTestWindowInShellWithBounds(
836 primary_root_window->GetBoundsInScreen());
837 ASSERT_EQ(primary_root_window,
838 focusable_window_in_primary_display->GetRootWindow());
839 aura::Window* focusable_window_in_secondary_display =
840 CreateTestWindowInShellWithBounds(
841 secondary_root_window->GetBoundsInScreen());
842 ASSERT_EQ(secondary_root_window,
843 focusable_window_in_secondary_display->GetRootWindow());
844
845 keyboard::KeyboardController::GetInstance()->ShowKeyboard(false);
846 EXPECT_TRUE(Shell::GetContainer(primary_root_window,
847 kShellWindowId_VirtualKeyboardContainer));
848 EXPECT_FALSE(Shell::GetContainer(secondary_root_window,
849 kShellWindowId_VirtualKeyboardContainer));
850
851 // Move the focus to the secondary display.
852 focusable_window_in_secondary_display->Focus();
853 ASSERT_TRUE(focusable_window_in_secondary_display->HasFocus());
854
855 keyboard::KeyboardController::GetInstance()->ShowKeyboard(false);
856 ASSERT_FALSE(Shell::GetContainer(primary_root_window,
857 kShellWindowId_VirtualKeyboardContainer));
858 ASSERT_TRUE(Shell::GetContainer(secondary_root_window,
859 kShellWindowId_VirtualKeyboardContainer));
860
861 // Move back focus to the primary display.
862 focusable_window_in_primary_display->Focus();
863 ASSERT_TRUE(focusable_window_in_primary_display->HasFocus());
864
865 keyboard::KeyboardController::GetInstance()->ShowKeyboard(false);
866 EXPECT_TRUE(Shell::GetContainer(primary_root_window,
867 kShellWindowId_VirtualKeyboardContainer));
868 EXPECT_FALSE(Shell::GetContainer(secondary_root_window,
869 kShellWindowId_VirtualKeyboardContainer));
870}
871
872// Test for http://crbug.com/303429. Even if both of display don't have touch
873// capability, the virtual keyboard shows up on the specified display.
874TEST_F(VirtualKeyboardRootWindowControllerTest,
875 VirtualKeyboardShowOnSpecifiedDisplay) {
sky56ce72b72017-02-27 19:07:06876 // TODO: fails in mash. http://crbug.com/695640.
skye5fd1222017-04-12 18:43:23877 if (Shell::GetAshConfig() == Config::MASH)
sky56ce72b72017-02-27 19:07:06878 return;
879
yhanada7e20c9b12016-11-25 00:03:19880 UpdateDisplay("500x500,500x500");
sky56ce72b72017-02-27 19:07:06881 display::Display secondary_display = GetSecondaryDisplay();
yhanada7e20c9b12016-11-25 00:03:19882
883 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
884 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
885 aura::Window* secondary_root_window = root_windows[0] == primary_root_window
886 ? root_windows[1]
887 : root_windows[0];
888
889 ASSERT_TRUE(Shell::GetContainer(primary_root_window,
890 kShellWindowId_VirtualKeyboardContainer));
891 ASSERT_FALSE(Shell::GetContainer(secondary_root_window,
892 kShellWindowId_VirtualKeyboardContainer));
893
894 const int64_t secondary_display_id = secondary_display.id();
895 keyboard::KeyboardController::GetInstance()->ShowKeyboardInDisplay(
896 secondary_display_id);
897
898 EXPECT_FALSE(Shell::GetContainer(primary_root_window,
899 kShellWindowId_VirtualKeyboardContainer));
900 EXPECT_TRUE(Shell::GetContainer(secondary_root_window,
901 kShellWindowId_VirtualKeyboardContainer));
902}
903
[email protected]eff4c7f2013-08-13 01:45:50904// Test for http://crbug.com/263599. Virtual keyboard should be able to receive
905// events at blocked user session.
906TEST_F(VirtualKeyboardRootWindowControllerTest,
907 ClickVirtualKeyboardInBlockedWindow) {
[email protected]bf9cdb362013-10-25 19:22:45908 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28909 aura::Window* keyboard_container =
910 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]eff4c7f2013-08-13 01:45:50911 ASSERT_TRUE(keyboard_container);
912 keyboard_container->Show();
913
[email protected]4b01c922017-07-12 21:45:07914 aura::Window* contents_window =
915 keyboard::KeyboardController::GetInstance()->ui()->GetContentsWindow();
916 contents_window->SetBounds(gfx::Rect());
917 contents_window->Show();
[email protected]647b4842013-12-12 14:24:24918
xiyuanf1ff14d2017-03-20 20:28:14919 // Make sure no pending mouse events in the queue.
920 RunAllPendingInMessageLoop();
921
[email protected]3193ea722014-04-23 22:19:19922 ui::test::TestEventHandler handler;
923 root_window->AddPreTargetHandler(&handler);
[email protected]647b4842013-12-12 14:24:24924
[email protected]4b01c922017-07-12 21:45:07925 ui::test::EventGenerator event_generator(root_window, contents_window);
[email protected]eff4c7f2013-08-13 01:45:50926 event_generator.ClickLeftButton();
927 int expected_mouse_presses = 1;
[email protected]3193ea722014-04-23 22:19:19928 EXPECT_EQ(expected_mouse_presses, handler.num_mouse_events() / 2);
[email protected]eff4c7f2013-08-13 01:45:50929
930 for (int block_reason = FIRST_BLOCK_REASON;
jamescookb8dcef522016-06-25 14:42:55931 block_reason < NUMBER_OF_BLOCK_REASONS; ++block_reason) {
[email protected]eff4c7f2013-08-13 01:45:50932 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
933 event_generator.ClickLeftButton();
934 expected_mouse_presses++;
[email protected]3193ea722014-04-23 22:19:19935 EXPECT_EQ(expected_mouse_presses, handler.num_mouse_events() / 2);
[email protected]eff4c7f2013-08-13 01:45:50936 UnblockUserSession();
937 }
[email protected]3193ea722014-04-23 22:19:19938 root_window->RemovePreTargetHandler(&handler);
[email protected]eff4c7f2013-08-13 01:45:50939}
940
[email protected]45c66672013-10-01 22:48:56941// Test for http://crbug.com/299787. RootWindowController should delete
942// the old container since the keyboard controller creates a new window in
943// GetWindowContainer().
944TEST_F(VirtualKeyboardRootWindowControllerTest,
945 DeleteOldContainerOnVirtualKeyboardInit) {
[email protected]1025937e2014-02-13 01:25:50946 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28947 aura::Window* keyboard_container =
948 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]45c66672013-10-01 22:48:56949 ASSERT_TRUE(keyboard_container);
950 // Track the keyboard container window.
951 aura::WindowTracker tracker;
952 tracker.Add(keyboard_container);
jamescooke3d63f62017-01-12 07:12:40953 // Reinitialize the keyboard.
skycb4be5b2017-04-06 17:52:45954 Shell::Get()->CreateKeyboard();
[email protected]45c66672013-10-01 22:48:56955 // keyboard_container should no longer be present.
956 EXPECT_FALSE(tracker.Contains(keyboard_container));
957}
958
[email protected]1025937e2014-02-13 01:25:50959// Test for crbug.com/342524. After user login, the work space should restore to
960// full screen.
961TEST_F(VirtualKeyboardRootWindowControllerTest, RestoreWorkspaceAfterLogin) {
962 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28963 aura::Window* keyboard_container =
964 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]1025937e2014-02-13 01:25:50965 keyboard_container->Show();
966 keyboard::KeyboardController* controller =
[email protected]a0b3fb882014-04-07 19:26:03967 keyboard::KeyboardController::GetInstance();
[email protected]4b01c922017-07-12 21:45:07968 aura::Window* contents_window = controller->ui()->GetContentsWindow();
969 contents_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
bshea0a57802015-04-08 18:21:29970 root_window->bounds(), 100));
[email protected]4b01c922017-07-12 21:45:07971 contents_window->Show();
[email protected]1025937e2014-02-13 01:25:50972
oshimaf84b0da722016-04-27 19:47:19973 gfx::Rect before =
974 display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
[email protected]1025937e2014-02-13 01:25:50975
976 // Notify keyboard bounds changing.
bshea0a57802015-04-08 18:21:29977 controller->NotifyKeyboardBoundsChanging(keyboard_container->bounds());
[email protected]1025937e2014-02-13 01:25:50978
[email protected]25df7ad2014-04-30 18:10:25979 if (!keyboard::IsKeyboardOverscrollEnabled()) {
oshimaf84b0da722016-04-27 19:47:19980 gfx::Rect after =
981 display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
[email protected]25df7ad2014-04-30 18:10:25982 EXPECT_LT(after, before);
983 }
[email protected]1025937e2014-02-13 01:25:50984
985 // Mock a login user profile change to reinitialize the keyboard.
jamescooke3d63f62017-01-12 07:12:40986 mojom::SessionInfoPtr info = mojom::SessionInfo::New();
987 info->state = session_manager::SessionState::ACTIVE;
sky5ad143a2017-03-22 04:31:23988 Shell::Get()->session_controller()->SetSessionInfo(std::move(info));
oshimaf84b0da722016-04-27 19:47:19989 EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().work_area(),
990 before);
[email protected]1025937e2014-02-13 01:25:50991}
992
[email protected]602022b2014-03-31 17:07:31993// Ensure that system modal dialogs do not block events targeted at the virtual
994// keyboard.
995TEST_F(VirtualKeyboardRootWindowControllerTest, ClickWithActiveModalDialog) {
996 aura::Window* root_window = Shell::GetPrimaryRootWindow();
[email protected]093b8d642014-04-03 20:59:28997 aura::Window* keyboard_container =
998 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
[email protected]602022b2014-03-31 17:07:31999 ASSERT_TRUE(keyboard_container);
1000 keyboard_container->Show();
1001
[email protected]4b01c922017-07-12 21:45:071002 aura::Window* contents_window =
1003 keyboard::KeyboardController::GetInstance()->ui()->GetContentsWindow();
1004 contents_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
bshea0a57802015-04-08 18:21:291005 root_window->bounds(), 100));
[email protected]3193ea722014-04-23 22:19:191006
1007 ui::test::TestEventHandler handler;
1008 root_window->AddPreTargetHandler(&handler);
[email protected]73c9fd02014-07-28 01:48:521009 ui::test::EventGenerator root_window_event_generator(root_window);
1010 ui::test::EventGenerator keyboard_event_generator(root_window,
[email protected]4b01c922017-07-12 21:45:071011 contents_window);
[email protected]602022b2014-03-31 17:07:311012
jamescookb8dcef522016-06-25 14:42:551013 views::Widget* modal_widget = CreateModalWidget(gfx::Rect(300, 10, 100, 100));
[email protected]602022b2014-03-31 17:07:311014
1015 // Verify that mouse events to the root window are block with a visble modal
1016 // dialog.
1017 root_window_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:191018 EXPECT_EQ(0, handler.num_mouse_events());
[email protected]602022b2014-03-31 17:07:311019
1020 // Verify that event dispatch to the virtual keyboard is unblocked.
1021 keyboard_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:191022 EXPECT_EQ(1, handler.num_mouse_events() / 2);
[email protected]602022b2014-03-31 17:07:311023
1024 modal_widget->Close();
1025
1026 // Verify that mouse events are now unblocked to the root window.
1027 root_window_event_generator.ClickLeftButton();
[email protected]3193ea722014-04-23 22:19:191028 EXPECT_EQ(2, handler.num_mouse_events() / 2);
1029 root_window->RemovePreTargetHandler(&handler);
[email protected]602022b2014-03-31 17:07:311030}
1031
[email protected]2082d7d2014-05-13 14:44:231032// Ensure that the visible area for scrolling the text caret excludes the
1033// region occluded by the on-screen keyboard.
1034TEST_F(VirtualKeyboardRootWindowControllerTest, EnsureCaretInWorkArea) {
1035 keyboard::KeyboardController* keyboard_controller =
1036 keyboard::KeyboardController::GetInstance();
ben974286a2015-10-10 00:45:121037 keyboard::KeyboardUI* ui = keyboard_controller->ui();
[email protected]2082d7d2014-05-13 14:44:231038
1039 MockTextInputClient text_input_client;
ben974286a2015-10-10 00:45:121040 ui::InputMethod* input_method = ui->GetInputMethod();
[email protected]2082d7d2014-05-13 14:44:231041 ASSERT_TRUE(input_method);
shuchen4e09795a2015-06-15 15:07:201042 input_method->SetFocusedTextInputClient(&text_input_client);
[email protected]2082d7d2014-05-13 14:44:231043
1044 aura::Window* root_window = Shell::GetPrimaryRootWindow();
1045 aura::Window* keyboard_container =
1046 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
1047 ASSERT_TRUE(keyboard_container);
1048 keyboard_container->Show();
1049
1050 const int keyboard_height = 100;
[email protected]4b01c922017-07-12 21:45:071051 aura::Window* contents_window = ui->GetContentsWindow();
1052 contents_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
bshea0a57802015-04-08 18:21:291053 root_window->bounds(), keyboard_height));
[email protected]4b01c922017-07-12 21:45:071054 contents_window->Show();
[email protected]2082d7d2014-05-13 14:44:231055
ben974286a2015-10-10 00:45:121056 ui->EnsureCaretInWorkArea();
bshea0a57802015-04-08 18:21:291057 ASSERT_EQ(root_window->bounds().width(),
yhanada0ddd3462016-12-08 05:04:181058 text_input_client.caret_exclude_rect().width());
1059 ASSERT_EQ(keyboard_height, text_input_client.caret_exclude_rect().height());
[email protected]00a386792014-06-16 15:09:201060
yhanada268490f2017-05-10 07:41:281061 input_method->SetFocusedTextInputClient(nullptr);
[email protected]2082d7d2014-05-13 14:44:231062}
1063
yhanada0ddd3462016-12-08 05:04:181064TEST_F(VirtualKeyboardRootWindowControllerTest,
1065 EnsureCaretInWorkAreaWithMultipleDisplays) {
sky56ce72b72017-02-27 19:07:061066 // TODO: fails in mash. http://crbug.com/695640.
skye5fd1222017-04-12 18:43:231067 if (Shell::GetAshConfig() == Config::MASH)
sky56ce72b72017-02-27 19:07:061068 return;
1069
yhanada0ddd3462016-12-08 05:04:181070 UpdateDisplay("500x500,600x600");
1071 const int64_t primary_display_id =
1072 display::Screen::GetScreen()->GetPrimaryDisplay().id();
sky56ce72b72017-02-27 19:07:061073 const int64_t secondary_display_id = GetSecondaryDisplay().id();
yhanada0ddd3462016-12-08 05:04:181074 ASSERT_NE(primary_display_id, secondary_display_id);
1075
1076 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1077 ASSERT_EQ(static_cast<size_t>(2), root_windows.size());
1078 aura::Window* primary_root_window = root_windows[0];
1079 aura::Window* secondary_root_window = root_windows[1];
1080
1081 keyboard::KeyboardController* keyboard_controller =
1082 keyboard::KeyboardController::GetInstance();
1083 keyboard::KeyboardUI* ui = keyboard_controller->ui();
1084
1085 MockTextInputClient text_input_client;
1086 ui::InputMethod* input_method = ui->GetInputMethod();
1087 ASSERT_TRUE(input_method);
1088 input_method->SetFocusedTextInputClient(&text_input_client);
1089
1090 const int keyboard_height = 100;
1091 // Check that the keyboard on the primary screen doesn't cover the window on
1092 // the secondary screen.
1093 aura::Window* keyboard_container = Shell::GetContainer(
1094 primary_root_window, kShellWindowId_VirtualKeyboardContainer);
1095 ASSERT_TRUE(keyboard_container);
1096 keyboard_container->Show();
[email protected]4b01c922017-07-12 21:45:071097 aura::Window* contents_window = ui->GetContentsWindow();
1098 contents_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
yhanada0ddd3462016-12-08 05:04:181099 primary_root_window->bounds(), keyboard_height));
[email protected]4b01c922017-07-12 21:45:071100 contents_window->Show();
yhanada0ddd3462016-12-08 05:04:181101
yhanada268490f2017-05-10 07:41:281102 ui->EnsureCaretInWorkArea();
yhanada0ddd3462016-12-08 05:04:181103 EXPECT_TRUE(primary_root_window->GetBoundsInScreen().Contains(
1104 text_input_client.caret_exclude_rect()));
yhanada268490f2017-05-10 07:41:281105 EXPECT_EQ(primary_root_window->GetBoundsInScreen().width(),
1106 text_input_client.caret_exclude_rect().width());
yhanada0ddd3462016-12-08 05:04:181107 EXPECT_FALSE(secondary_root_window->GetBoundsInScreen().Contains(
1108 text_input_client.caret_exclude_rect()));
1109
1110 // Move the keyboard into the secondary display and check that the keyboard
1111 // doesn't cover the window on the primary screen.
1112 keyboard_controller->ShowKeyboardInDisplay(secondary_display_id);
[email protected]4b01c922017-07-12 21:45:071113 contents_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds(
yhanada0ddd3462016-12-08 05:04:181114 secondary_root_window->bounds(), keyboard_height));
1115
1116 ui->EnsureCaretInWorkArea();
1117 EXPECT_FALSE(primary_root_window->GetBoundsInScreen().Contains(
1118 text_input_client.caret_exclude_rect()));
1119 EXPECT_TRUE(secondary_root_window->GetBoundsInScreen().Contains(
1120 text_input_client.caret_exclude_rect()));
yhanada268490f2017-05-10 07:41:281121 EXPECT_EQ(secondary_root_window->GetBoundsInScreen().width(),
1122 text_input_client.caret_exclude_rect().width());
yhanada0ddd3462016-12-08 05:04:181123
1124 input_method->SetFocusedTextInputClient(nullptr);
1125}
1126
kevers23f3987d2014-09-17 13:50:121127// Tests that the virtual keyboard does not block context menus. The virtual
1128// keyboard should appear in front of most content, but not context menus. See
1129// crbug/377180.
1130TEST_F(VirtualKeyboardRootWindowControllerTest, ZOrderTest) {
1131 UpdateDisplay("800x600");
1132 keyboard::KeyboardController* keyboard_controller =
1133 keyboard::KeyboardController::GetInstance();
ben974286a2015-10-10 00:45:121134 keyboard::KeyboardUI* ui = keyboard_controller->ui();
kevers23f3987d2014-09-17 13:50:121135
1136 aura::Window* root_window = Shell::GetPrimaryRootWindow();
1137 aura::Window* keyboard_container =
1138 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
1139 ASSERT_TRUE(keyboard_container);
1140 keyboard_container->Show();
1141
1142 const int keyboard_height = 200;
[email protected]4b01c922017-07-12 21:45:071143 aura::Window* contents_window = ui->GetContentsWindow();
bshea0a57802015-04-08 18:21:291144 gfx::Rect keyboard_bounds = keyboard::FullWidthKeyboardBoundsFromRootBounds(
1145 root_window->bounds(), keyboard_height);
[email protected]4b01c922017-07-12 21:45:071146 contents_window->SetBounds(keyboard_bounds);
1147 contents_window->Show();
kevers23f3987d2014-09-17 13:50:121148
1149 ui::test::EventGenerator generator(root_window);
1150
1151 // Cover the screen with two windows: a normal window on the left side and a
1152 // context menu on the right side. When the virtual keyboard is displayed it
1153 // partially occludes the normal window, but not the context menu. Compute
1154 // positions for generating synthetic click events to perform hit tests,
1155 // ensuring the correct window layering. 'top' is above the VK, whereas
1156 // 'bottom' lies within the VK. 'left' is centered in the normal window, and
1157 // 'right' is centered in the context menu.
1158 int window_height = keyboard_bounds.bottom();
1159 int window_width = keyboard_bounds.width() / 2;
1160 int left = window_width / 2;
1161 int right = 3 * window_width / 2;
1162 int top = keyboard_bounds.y() / 2;
1163 int bottom = window_height - keyboard_height / 2;
1164
1165 // Normal window is partially occluded by the virtual keyboard.
1166 aura::test::TestWindowDelegate delegate;
dchenga94547472016-04-08 08:41:111167 std::unique_ptr<aura::Window> normal(
1168 CreateTestWindowInShellWithDelegateAndType(
Thiago Farina627fba952017-05-24 21:15:261169 &delegate, aura::client::WINDOW_TYPE_NORMAL, 0,
dchenga94547472016-04-08 08:41:111170 gfx::Rect(0, 0, window_width, window_height)));
kevers23f3987d2014-09-17 13:50:121171 normal->set_owned_by_parent(false);
1172 normal->Show();
1173 TargetHitTestEventHandler normal_handler;
1174 normal->AddPreTargetHandler(&normal_handler);
1175
1176 // Test that only the click on the top portion of the window is picked up. The
1177 // click on the bottom hits the virtual keyboard instead.
1178 generator.MoveMouseTo(left, top);
1179 generator.ClickLeftButton();
1180 EXPECT_EQ(1, normal_handler.num_mouse_events());
1181 generator.MoveMouseTo(left, bottom);
1182 generator.ClickLeftButton();
1183 EXPECT_EQ(1, normal_handler.num_mouse_events());
1184
1185 // Menu overlaps virtual keyboard.
1186 aura::test::TestWindowDelegate delegate2;
dchenga94547472016-04-08 08:41:111187 std::unique_ptr<aura::Window> menu(CreateTestWindowInShellWithDelegateAndType(
Thiago Farina627fba952017-05-24 21:15:261188 &delegate2, aura::client::WINDOW_TYPE_MENU, 0,
kevers23f3987d2014-09-17 13:50:121189 gfx::Rect(window_width, 0, window_width, window_height)));
1190 menu->set_owned_by_parent(false);
1191 menu->Show();
1192 TargetHitTestEventHandler menu_handler;
1193 menu->AddPreTargetHandler(&menu_handler);
1194
1195 // Test that both clicks register.
1196 generator.MoveMouseTo(right, top);
1197 generator.ClickLeftButton();
1198 EXPECT_EQ(1, menu_handler.num_mouse_events());
1199 generator.MoveMouseTo(right, bottom);
1200 generator.ClickLeftButton();
1201 EXPECT_EQ(2, menu_handler.num_mouse_events());
1202
1203 // Cleanup to ensure that the test windows are destroyed before their
1204 // delegates.
1205 normal.reset();
1206 menu.reset();
1207}
1208
kevers0e450492014-09-30 16:02:311209// Tests that the virtual keyboard correctly resizes with a change to display
1210// orientation. See crbug/417612.
jamescook01bf23e72017-01-09 19:58:151211TEST_F(VirtualKeyboardRootWindowControllerTest, DisplayRotation) {
kevers0e450492014-09-30 16:02:311212 UpdateDisplay("800x600");
1213 aura::Window* root_window = Shell::GetPrimaryRootWindow();
1214 aura::Window* keyboard_container =
1215 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
1216 ASSERT_TRUE(keyboard_container);
bshea0a57802015-04-08 18:21:291217 keyboard::KeyboardController* keyboard_controller =
1218 keyboard::KeyboardController::GetInstance();
1219 keyboard_controller->ShowKeyboard(false);
[email protected]4b01c922017-07-12 21:45:071220 keyboard_controller->ui()->GetContentsWindow()->SetBounds(
bshea0a57802015-04-08 18:21:291221 gfx::Rect(0, 400, 800, 200));
1222 EXPECT_EQ("0,400 800x200", keyboard_container->bounds().ToString());
kevers0e450492014-09-30 16:02:311223
1224 UpdateDisplay("600x800");
bshea0a57802015-04-08 18:21:291225 EXPECT_EQ("0,600 600x200", keyboard_container->bounds().ToString());
kevers0e450492014-09-30 16:02:311226}
1227
[email protected]f1853122012-06-27 16:21:261228} // namespace test
1229} // namespace ash