blob: ac03c1042d19c30b095f49caa2322b137c053f51 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
5#include "ash/wm/system_modal_container_layout_manager.h"
6
7#include "ash/root_window_controller.h"
Bo Liu5c02ac12014-05-01 10:37:37 -07008#include "ash/session/session_state_delegate.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009#include "ash/shell.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "ash/shell_window_ids.h"
11#include "ash/test/ash_test_base.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "ash/wm/window_util.h"
Ben Murdochc5cede92014-04-10 11:22:14 +010013#include "base/command_line.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "base/compiler_specific.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "base/run_loop.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016#include "ui/aura/test/event_generator.h"
17#include "ui/aura/window.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000018#include "ui/aura/window_event_dispatcher.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "ui/compositor/layer.h"
Ben Murdochc5cede92014-04-10 11:22:14 +010020#include "ui/compositor/scoped_animation_duration_scale_mode.h"
21#include "ui/compositor/test/layer_animator_test_controller.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000022#include "ui/gfx/screen.h"
Ben Murdochc5cede92014-04-10 11:22:14 +010023#include "ui/keyboard/keyboard_controller.h"
24#include "ui/keyboard/keyboard_controller_proxy.h"
25#include "ui/keyboard/keyboard_switches.h"
26#include "ui/keyboard/keyboard_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027#include "ui/views/test/capture_tracking_view.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000028#include "ui/views/widget/widget.h"
29#include "ui/views/widget/widget_delegate.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000030#include "ui/wm/core/window_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000031
32namespace ash {
33namespace test {
34
35namespace {
36
37aura::Window* GetModalContainer() {
38 return Shell::GetPrimaryRootWindowController()->GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +010039 ash::kShellWindowId_SystemModalContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000040}
41
42bool AllRootWindowsHaveModalBackgroundsForContainer(int container_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000043 std::vector<aura::Window*> containers =
44 Shell::GetContainersFromAllRootWindows(container_id, NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000045 bool has_modal_screen = !containers.empty();
46 for (std::vector<aura::Window*>::iterator iter = containers.begin();
47 iter != containers.end(); ++iter) {
Ben Murdochc5cede92014-04-10 11:22:14 +010048 has_modal_screen &= static_cast<SystemModalContainerLayoutManager*>(
49 (*iter)->layout_manager())->has_modal_background();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050 }
51 return has_modal_screen;
52}
53
54bool AllRootWindowsHaveLockedModalBackgrounds() {
55 return AllRootWindowsHaveModalBackgroundsForContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +010056 kShellWindowId_LockSystemModalContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000057}
58
59bool AllRootWindowsHaveModalBackgrounds() {
60 return AllRootWindowsHaveModalBackgroundsForContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +010061 kShellWindowId_SystemModalContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000062}
63
64class TestWindow : public views::WidgetDelegateView {
65 public:
66 explicit TestWindow(bool modal) : modal_(modal) {}
67 virtual ~TestWindow() {}
68
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000069 // The window needs be closed from widget in order for
70 // aura::client::kModalKey property to be reset.
71 static void CloseTestWindow(aura::Window* window) {
72 views::Widget::GetWidgetForNativeWindow(window)->Close();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073 }
74
75 // Overridden from views::View:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010076 virtual gfx::Size GetPreferredSize() const OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000077 return gfx::Size(50, 50);
78 }
79
80 // Overridden from views::WidgetDelegate:
81 virtual views::View* GetContentsView() OVERRIDE {
82 return this;
83 }
84 virtual ui::ModalType GetModalType() const OVERRIDE {
85 return modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
86 }
87
88 private:
89 bool modal_;
90
91 DISALLOW_COPY_AND_ASSIGN(TestWindow);
92};
93
94class EventTestWindow : public TestWindow {
95 public:
96 explicit EventTestWindow(bool modal) : TestWindow(modal),
97 mouse_presses_(0) {}
98 virtual ~EventTestWindow() {}
99
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000100 aura::Window* OpenTestWindowWithContext(aura::Window* context) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000101 views::Widget* widget =
102 views::Widget::CreateWindowWithContext(this, context);
103 widget->Show();
104 return widget->GetNativeView();
105 }
106
107 aura::Window* OpenTestWindowWithParent(aura::Window* parent) {
108 DCHECK(parent);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000109 views::Widget* widget =
110 views::Widget::CreateWindowWithParent(this, parent);
111 widget->Show();
112 return widget->GetNativeView();
113 }
114
115 // Overridden from views::View:
116 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
117 mouse_presses_++;
118 return false;
119 }
120
121 int mouse_presses() const { return mouse_presses_; }
122 private:
123 int mouse_presses_;
124
125 DISALLOW_COPY_AND_ASSIGN(EventTestWindow);
126};
127
128class TransientWindowObserver : public aura::WindowObserver {
129 public:
130 TransientWindowObserver() : destroyed_(false) {}
131 virtual ~TransientWindowObserver() {}
132
133 bool destroyed() const { return destroyed_; }
134
135 // Overridden from aura::WindowObserver:
136 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
137 destroyed_ = true;
138 }
139
140 private:
141 bool destroyed_;
142
143 DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
144};
145
146} // namespace
147
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000148class SystemModalContainerLayoutManagerTest : public AshTestBase {
149 public:
Ben Murdochc5cede92014-04-10 11:22:14 +0100150 virtual void SetUp() OVERRIDE {
151 // Allow a virtual keyboard (and initialize it per default).
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100152 CommandLine::ForCurrentProcess()->AppendSwitch(
153 keyboard::switches::kEnableVirtualKeyboard);
Ben Murdochc5cede92014-04-10 11:22:14 +0100154 AshTestBase::SetUp();
155 Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
156 keyboard::KeyboardController::GetInstance());
157 }
158
159 virtual void TearDown() OVERRIDE {
160 Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
161 keyboard::KeyboardController::GetInstance());
162 AshTestBase::TearDown();
163 }
164
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000165 aura::Window* OpenToplevelTestWindow(bool modal) {
166 views::Widget* widget = views::Widget::CreateWindowWithContext(
167 new TestWindow(modal), CurrentContext());
168 widget->Show();
169 return widget->GetNativeView();
170 }
171
172 aura::Window* OpenTestWindowWithParent(aura::Window* parent, bool modal) {
173 views::Widget* widget =
174 views::Widget::CreateWindowWithParent(new TestWindow(modal), parent);
175 widget->Show();
176 return widget->GetNativeView();
177 }
Ben Murdochc5cede92014-04-10 11:22:14 +0100178
179 // Show or hide the keyboard.
180 void ShowKeyboard(bool show) {
181 keyboard::KeyboardController* keyboard =
182 keyboard::KeyboardController::GetInstance();
183 ASSERT_TRUE(keyboard);
184 if (show == keyboard->keyboard_visible())
185 return;
186
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100187 if (show) {
188 keyboard->ShowKeyboard(true);
189 if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
190 keyboard->proxy()->GetKeyboardWindow()->SetBounds(
191 keyboard::KeyboardBoundsFromWindowBounds(
192 keyboard->GetContainerWindow()->bounds(), 100));
193 }
194 } else {
Ben Murdochc5cede92014-04-10 11:22:14 +0100195 keyboard->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100196 }
Ben Murdochc5cede92014-04-10 11:22:14 +0100197
198 DCHECK_EQ(show, keyboard->keyboard_visible());
199 }
200
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000201};
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000202
203TEST_F(SystemModalContainerLayoutManagerTest, NonModalTransient) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000204 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
205 aura::Window* transient = OpenTestWindowWithParent(parent.get(), false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000206 TransientWindowObserver destruction_observer;
207 transient->AddObserver(&destruction_observer);
208
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000209 EXPECT_EQ(parent.get(), ::wm::GetTransientParent(transient));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000210 EXPECT_EQ(parent->parent(), transient->parent());
211
212 // The transient should be destroyed with its parent.
213 parent.reset();
214 EXPECT_TRUE(destruction_observer.destroyed());
215}
216
217TEST_F(SystemModalContainerLayoutManagerTest, ModalTransient) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000218 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000219 // parent should be active.
220 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000221 aura::Window* t1 = OpenTestWindowWithParent(parent.get(), true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000222
223 TransientWindowObserver do1;
224 t1->AddObserver(&do1);
225
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000226 EXPECT_EQ(parent.get(), ::wm::GetTransientParent(t1));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000227 EXPECT_EQ(GetModalContainer(), t1->parent());
228
229 // t1 should now be active.
230 EXPECT_TRUE(wm::IsActiveWindow(t1));
231
232 // Attempting to click the parent should result in no activation change.
233 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
234 e1.ClickLeftButton();
235 EXPECT_TRUE(wm::IsActiveWindow(t1));
236
237 // Now open another modal transient parented to the original modal transient.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000238 aura::Window* t2 = OpenTestWindowWithParent(t1, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239 TransientWindowObserver do2;
240 t2->AddObserver(&do2);
241
242 EXPECT_TRUE(wm::IsActiveWindow(t2));
243
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000244 EXPECT_EQ(t1, ::wm::GetTransientParent(t2));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000245 EXPECT_EQ(GetModalContainer(), t2->parent());
246
247 // t2 should still be active, even after clicking on t1.
248 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1);
249 e2.ClickLeftButton();
250 EXPECT_TRUE(wm::IsActiveWindow(t2));
251
252 // Both transients should be destroyed with parent.
253 parent.reset();
254 EXPECT_TRUE(do1.destroyed());
255 EXPECT_TRUE(do2.destroyed());
256}
257
258TEST_F(SystemModalContainerLayoutManagerTest, ModalNonTransient) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000259 scoped_ptr<aura::Window> t1(OpenToplevelTestWindow(true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000260 // parent should be active.
261 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
262 TransientWindowObserver do1;
263 t1->AddObserver(&do1);
264
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000265 EXPECT_EQ(NULL, ::wm::GetTransientParent(t1.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000266 EXPECT_EQ(GetModalContainer(), t1->parent());
267
268 // t1 should now be active.
269 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
270
271 // Attempting to click the parent should result in no activation change.
272 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(),
273 Shell::GetPrimaryRootWindow());
274 e1.ClickLeftButton();
275 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
276
277 // Now open another modal transient parented to the original modal transient.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000278 aura::Window* t2 = OpenTestWindowWithParent(t1.get(), true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000279 TransientWindowObserver do2;
280 t2->AddObserver(&do2);
281
282 EXPECT_TRUE(wm::IsActiveWindow(t2));
283
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000284 EXPECT_EQ(t1, ::wm::GetTransientParent(t2));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000285 EXPECT_EQ(GetModalContainer(), t2->parent());
286
287 // t2 should still be active, even after clicking on t1.
288 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1.get());
289 e2.ClickLeftButton();
290 EXPECT_TRUE(wm::IsActiveWindow(t2));
291
292 // Both transients should be destroyed with parent.
293 t1.reset();
294 EXPECT_TRUE(do1.destroyed());
295 EXPECT_TRUE(do2.destroyed());
296}
297
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000298// Tests that we can activate an unrelated window after a modal window is closed
299// for a window.
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100300TEST_F(SystemModalContainerLayoutManagerTest, CanActivateAfterEndModalSession) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000301 scoped_ptr<aura::Window> unrelated(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000302 unrelated->SetBounds(gfx::Rect(100, 100, 50, 50));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000303 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000304 // parent should be active.
305 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
306
307 scoped_ptr<aura::Window> transient(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000308 OpenTestWindowWithParent(parent.get(), true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000309 // t1 should now be active.
310 EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
311
312 // Attempting to click the parent should result in no activation change.
313 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
314 e1.ClickLeftButton();
315 EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
316
317 // Now close the transient.
318 transient->Hide();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000319 TestWindow::CloseTestWindow(transient.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000320
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000321 base::RunLoop().RunUntilIdle();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000322
323 // parent should now be active again.
324 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
325
326 // Attempting to click unrelated should activate it.
327 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), unrelated.get());
328 e2.ClickLeftButton();
329 EXPECT_TRUE(wm::IsActiveWindow(unrelated.get()));
330}
331
332TEST_F(SystemModalContainerLayoutManagerTest, EventFocusContainers) {
333 // Create a normal window and attempt to receive a click event.
334 EventTestWindow* main_delegate = new EventTestWindow(false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000335 scoped_ptr<aura::Window> main(
336 main_delegate->OpenTestWindowWithContext(CurrentContext()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000337 EXPECT_TRUE(wm::IsActiveWindow(main.get()));
338 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), main.get());
339 e1.ClickLeftButton();
340 EXPECT_EQ(1, main_delegate->mouse_presses());
341
342 // Create a modal window for the main window and verify that the main window
343 // no longer receives mouse events.
344 EventTestWindow* transient_delegate = new EventTestWindow(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000345 aura::Window* transient =
346 transient_delegate->OpenTestWindowWithParent(main.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000347 EXPECT_TRUE(wm::IsActiveWindow(transient));
348 e1.ClickLeftButton();
349 EXPECT_EQ(1, transient_delegate->mouse_presses());
350
Ben Murdochbbcdd452013-07-25 10:06:34 +0100351 for (int block_reason = FIRST_BLOCK_REASON;
352 block_reason < NUMBER_OF_BLOCK_REASONS;
353 ++block_reason) {
354 // Create a window in the lock screen container and ensure that it receives
355 // the mouse event instead of the modal window (crbug.com/110920).
356 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
357 EventTestWindow* lock_delegate = new EventTestWindow(false);
358 scoped_ptr<aura::Window> lock(lock_delegate->OpenTestWindowWithParent(
359 Shell::GetPrimaryRootWindowController()->GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100360 ash::kShellWindowId_LockScreenContainer)));
Ben Murdochbbcdd452013-07-25 10:06:34 +0100361 EXPECT_TRUE(wm::IsActiveWindow(lock.get()));
362 e1.ClickLeftButton();
363 EXPECT_EQ(1, lock_delegate->mouse_presses());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000364
Ben Murdochbbcdd452013-07-25 10:06:34 +0100365 // Make sure that a modal container created by the lock screen can still
366 // receive mouse events.
367 EventTestWindow* lock_modal_delegate = new EventTestWindow(true);
368 aura::Window* lock_modal =
369 lock_modal_delegate->OpenTestWindowWithParent(lock.get());
370 EXPECT_TRUE(wm::IsActiveWindow(lock_modal));
371 e1.ClickLeftButton();
372 // Verify that none of the other containers received any more mouse presses.
373 EXPECT_EQ(1, lock_modal_delegate->mouse_presses());
374 EXPECT_EQ(1, lock_delegate->mouse_presses());
375 EXPECT_EQ(1, main_delegate->mouse_presses());
376 EXPECT_EQ(1, transient_delegate->mouse_presses());
377 UnblockUserSession();
378 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000379}
380
381// Makes sure we don't crash if a modal window is shown while the parent window
382// is hidden.
383TEST_F(SystemModalContainerLayoutManagerTest, ShowModalWhileHidden) {
384 // Hide the lock screen.
Ben Murdochc5cede92014-04-10 11:22:14 +0100385 Shell::GetPrimaryRootWindowController()
386 ->GetContainer(kShellWindowId_SystemModalContainer)
387 ->layer()
388 ->SetOpacity(0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000389
390 // Create a modal window.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000391 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000392 scoped_ptr<aura::Window> modal_window(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000393 OpenTestWindowWithParent(parent.get(), true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000394 parent->Show();
395 modal_window->Show();
396}
397
398// Verifies we generate a capture lost when showing a modal window.
399TEST_F(SystemModalContainerLayoutManagerTest, ChangeCapture) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000400 views::Widget* widget = views::Widget::CreateWindowWithContext(
401 new TestWindow(false), CurrentContext());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000402 scoped_ptr<aura::Window> widget_window(widget->GetNativeView());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000403 views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000404 widget->GetContentsView()->AddChildView(view);
405 view->SetBoundsRect(widget->GetContentsView()->bounds());
406 widget->Show();
407
408 gfx::Point center(view->width() / 2, view->height() / 2);
409 views::View::ConvertPointToScreen(view, &center);
410 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center);
411 generator.PressLeftButton();
412 EXPECT_TRUE(view->got_press());
413 scoped_ptr<aura::Window> modal_window(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000414 OpenTestWindowWithParent(widget->GetNativeView(), true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000415 modal_window->Show();
416 EXPECT_TRUE(view->got_capture_lost());
417}
418
419// Verifies that the window gets moved into the visible screen area upon screen
420// resize.
421TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) {
422 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000423 scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(),
424 true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000425 main->SetBounds(gfx::Rect(924, 668, 100, 100));
426 // We set now the bounds of the root window to something new which will
427 // Then trigger the repos operation.
428 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600));
429
430 gfx::Rect bounds = main->bounds();
431 EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100));
432}
433
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100434// Verifies that centered windows will remain centered after the visible screen
435// area changed.
436TEST_F(SystemModalContainerLayoutManagerTest, KeepCentered) {
437 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600));
438 scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(),
439 true));
440 // Center the window.
441 main->SetBounds(gfx::Rect((800 - 512) / 2, (600 - 256) / 2, 512, 256));
442
443 // We set now the bounds of the root window to something new which will
444 // Then trigger the reposition operation.
445 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768));
446
447 // The window should still be centered.
448 gfx::Rect bounds = main->bounds();
449 EXPECT_EQ(bounds.ToString(), gfx::Rect(256, 256, 512, 256).ToString());
450}
451
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000452TEST_F(SystemModalContainerLayoutManagerTest, ShowNormalBackgroundOrLocked) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000453 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000454 scoped_ptr<aura::Window> modal_window(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000455 OpenTestWindowWithParent(parent.get(), true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000456 parent->Show();
457 modal_window->Show();
458
459 // Normal system modal window. Shows normal system modal background and not
460 // locked.
461 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
462 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
463
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000464 TestWindow::CloseTestWindow(modal_window.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000465 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
466 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
467
Ben Murdochbbcdd452013-07-25 10:06:34 +0100468 for (int block_reason = FIRST_BLOCK_REASON;
469 block_reason < NUMBER_OF_BLOCK_REASONS;
470 ++block_reason) {
471 // Normal system modal window while blocked. Shows blocked system modal
472 // background.
473 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
474 scoped_ptr<aura::Window> lock_parent(OpenTestWindowWithParent(
475 Shell::GetPrimaryRootWindowController()->GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100476 ash::kShellWindowId_LockScreenContainer),
Ben Murdochbbcdd452013-07-25 10:06:34 +0100477 false));
478 scoped_ptr<aura::Window> lock_modal_window(OpenTestWindowWithParent(
479 lock_parent.get(), true));
480 lock_parent->Show();
481 lock_modal_window->Show();
482 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
483 EXPECT_TRUE(AllRootWindowsHaveLockedModalBackgrounds());
484 TestWindow::CloseTestWindow(lock_modal_window.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000485
Ben Murdochbbcdd452013-07-25 10:06:34 +0100486 // Normal system modal window while blocked, but it belongs to the normal
487 // window. Shouldn't show blocked system modal background, but normal.
488 scoped_ptr<aura::Window> modal_window(
489 OpenTestWindowWithParent(parent.get(), true));
490 modal_window->Show();
491 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
492 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
493 TestWindow::CloseTestWindow(modal_window.release());
494 UnblockUserSession();
495 // Here we should check the behavior of the locked system modal dialog when
496 // unlocked, but such case isn't handled very well right now.
497 // See crbug.com/157660
498 // TODO(mukai): add the test case when the bug is fixed.
499 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000500}
501
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100502TEST_F(SystemModalContainerLayoutManagerTest, MultiDisplays) {
503 if (!SupportsMultipleDisplays())
504 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000505
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000506 UpdateDisplay("500x500,500x500");
507
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000508 scoped_ptr<aura::Window> normal(OpenToplevelTestWindow(false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000509 normal->SetBounds(gfx::Rect(100, 100, 50, 50));
510
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000511 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000512 EXPECT_EQ(2U, root_windows.size());
513 aura::Window* container1 = Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100514 root_windows[0], ash::kShellWindowId_SystemModalContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000515 aura::Window* container2 = Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100516 root_windows[1], ash::kShellWindowId_SystemModalContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000517
518 scoped_ptr<aura::Window> modal1(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000519 OpenTestWindowWithParent(container1, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000520 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
521 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
522
523 scoped_ptr<aura::Window> modal11(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000524 OpenTestWindowWithParent(container1, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000525 EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
526
527 scoped_ptr<aura::Window> modal2(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000528 OpenTestWindowWithParent(container2, true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000529 EXPECT_TRUE(wm::IsActiveWindow(modal2.get()));
530
531 // Sanity check if they're on the correct containers.
532 EXPECT_EQ(container1, modal1->parent());
533 EXPECT_EQ(container1, modal11->parent());
534 EXPECT_EQ(container2, modal2->parent());
535
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000536 TestWindow::CloseTestWindow(modal2.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000537 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
538 EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
539
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000540 TestWindow::CloseTestWindow(modal11.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000541 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
542 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
543
544 UpdateDisplay("500x500");
545 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
546 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
547
548 UpdateDisplay("500x500,600x600");
549 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
550 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
551
552 // No more modal screen.
553 modal1->Hide();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000554 TestWindow::CloseTestWindow(modal1.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000555 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
556 EXPECT_TRUE(wm::IsActiveWindow(normal.get()));
557}
558
Ben Murdochc5cede92014-04-10 11:22:14 +0100559// Test that with the visible keyboard, an existing system modal dialog gets
560// positioned into the visible area.
561TEST_F(SystemModalContainerLayoutManagerTest,
562 SystemModalDialogGetPushedFromKeyboard) {
563 const gfx::Rect& container_bounds = GetModalContainer()->bounds();
564 // Place the window at the bottom of the screen.
565 gfx::Size modal_size(100, 100);
566 gfx::Point modal_origin = gfx::Point(
567 (container_bounds.right() - modal_size.width()) / 2, // X centered
568 container_bounds.bottom() - modal_size.height()); // at bottom
569 gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
570
571 // Create a modal window.
572 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
573 scoped_ptr<aura::Window> modal_window(
574 OpenTestWindowWithParent(parent.get(), true));
575 modal_window->SetBounds(modal_bounds);
576 parent->Show();
577 modal_window->Show();
578
579 EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
580
581 // The keyboard gets shown and the dialog should get pushed.
582 ShowKeyboard(true);
583 EXPECT_NE(modal_bounds.ToString(), modal_window->bounds().ToString());
584 EXPECT_GT(modal_bounds.y(), modal_window->bounds().y());
585 EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
586 EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
587
588 // After the keyboard is gone, the window will remain where it was.
589 ShowKeyboard(false);
590 EXPECT_NE(modal_bounds.ToString(), modal_window->bounds().ToString());
591 EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
592 EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
593}
594
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100595// Test that windows will not get cropped through the visible virtual keyboard -
596// if centered.
597TEST_F(SystemModalContainerLayoutManagerTest,
598 SystemModalDialogGetPushedButNotCroppedFromKeyboard) {
599 const gfx::Rect& container_bounds = GetModalContainer()->bounds();
600 const gfx::Size screen_size = Shell::GetPrimaryRootWindow()->bounds().size();
601 // Place the window at the bottom of the screen.
602 gfx::Size modal_size(100, screen_size.height() - 70);
603 gfx::Point modal_origin = gfx::Point(
604 (container_bounds.right() - modal_size.width()) / 2, // X centered
605 container_bounds.bottom() - modal_size.height()); // at bottom
606 gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
607
608 // Create a modal window.
609 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
610 scoped_ptr<aura::Window> modal_window(
611 OpenTestWindowWithParent(parent.get(), true));
612 modal_window->SetBounds(modal_bounds);
613 parent->Show();
614 modal_window->Show();
615
616 EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
617
618 // The keyboard gets shown and the dialog should get pushed up, but not get
619 // cropped (and aligned to the top).
620 ShowKeyboard(true);
621 EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
622 EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
623 EXPECT_EQ(0, modal_window->bounds().y());
624
625 ShowKeyboard(false);
626}
627
628// Test that windows will not get cropped through the visible virtual keyboard -
629// if not centered.
630TEST_F(SystemModalContainerLayoutManagerTest,
631 SystemModalDialogGetPushedButNotCroppedFromKeyboardIfNotCentered) {
632 const gfx::Size screen_size = Shell::GetPrimaryRootWindow()->bounds().size();
633 // Place the window at the bottom of the screen.
634 gfx::Size modal_size(100, screen_size.height() - 70);
635 gfx::Point modal_origin = gfx::Point(10, 20);
636 gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
637
638 // Create a modal window.
639 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
640 scoped_ptr<aura::Window> modal_window(
641 OpenTestWindowWithParent(parent.get(), true));
642 modal_window->SetBounds(modal_bounds);
643 parent->Show();
644 modal_window->Show();
645
646 EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
647
648 // The keyboard gets shown and the dialog should get pushed up, but not get
649 // cropped (and aligned to the top).
650 ShowKeyboard(true);
651 EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
652 EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
653 EXPECT_EQ(0, modal_window->bounds().y());
654
655 ShowKeyboard(false);
656}
657
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000658} // namespace test
659} // namespace ash