Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / ash / wm / system_modal_container_layout_manager_unittest.cc
blobe66678a583085be11ec15ae64c591906195f59bc
1 // 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.
5 #include "ash/wm/system_modal_container_layout_manager.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/session_state_delegate.h"
9 #include "ash/shell.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/test/ash_test_base.h"
12 #include "ash/wm/window_util.h"
13 #include "base/compiler_specific.h"
14 #include "base/run_loop.h"
15 #include "ui/aura/root_window.h"
16 #include "ui/aura/test/event_generator.h"
17 #include "ui/aura/window.h"
18 #include "ui/compositor/layer.h"
19 #include "ui/gfx/screen.h"
20 #include "ui/views/corewm/window_util.h"
21 #include "ui/views/test/capture_tracking_view.h"
22 #include "ui/views/widget/widget.h"
23 #include "ui/views/widget/widget_delegate.h"
25 namespace ash {
26 namespace test {
28 namespace {
30 aura::Window* GetModalContainer() {
31 return Shell::GetPrimaryRootWindowController()->GetContainer(
32 ash::internal::kShellWindowId_SystemModalContainer);
35 bool AllRootWindowsHaveModalBackgroundsForContainer(int container_id) {
36 std::vector<aura::Window*> containers =
37 Shell::GetContainersFromAllRootWindows(container_id, NULL);
38 bool has_modal_screen = !containers.empty();
39 for (std::vector<aura::Window*>::iterator iter = containers.begin();
40 iter != containers.end(); ++iter) {
41 has_modal_screen &=
42 static_cast<internal::SystemModalContainerLayoutManager*>(
43 (*iter)->layout_manager())->has_modal_background();
45 return has_modal_screen;
48 bool AllRootWindowsHaveLockedModalBackgrounds() {
49 return AllRootWindowsHaveModalBackgroundsForContainer(
50 internal::kShellWindowId_LockSystemModalContainer);
53 bool AllRootWindowsHaveModalBackgrounds() {
54 return AllRootWindowsHaveModalBackgroundsForContainer(
55 internal::kShellWindowId_SystemModalContainer);
58 class TestWindow : public views::WidgetDelegateView {
59 public:
60 explicit TestWindow(bool modal) : modal_(modal) {}
61 virtual ~TestWindow() {}
63 // The window needs be closed from widget in order for
64 // aura::client::kModalKey property to be reset.
65 static void CloseTestWindow(aura::Window* window) {
66 views::Widget::GetWidgetForNativeWindow(window)->Close();
69 // Overridden from views::View:
70 virtual gfx::Size GetPreferredSize() OVERRIDE {
71 return gfx::Size(50, 50);
74 // Overridden from views::WidgetDelegate:
75 virtual views::View* GetContentsView() OVERRIDE {
76 return this;
78 virtual ui::ModalType GetModalType() const OVERRIDE {
79 return modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
82 private:
83 bool modal_;
85 DISALLOW_COPY_AND_ASSIGN(TestWindow);
88 class EventTestWindow : public TestWindow {
89 public:
90 explicit EventTestWindow(bool modal) : TestWindow(modal),
91 mouse_presses_(0) {}
92 virtual ~EventTestWindow() {}
94 aura::Window* OpenTestWindowWithContext(aura::Window* context) {
95 views::Widget* widget =
96 views::Widget::CreateWindowWithContext(this, context);
97 widget->Show();
98 return widget->GetNativeView();
101 aura::Window* OpenTestWindowWithParent(aura::Window* parent) {
102 DCHECK(parent);
103 views::Widget* widget =
104 views::Widget::CreateWindowWithParent(this, parent);
105 widget->Show();
106 return widget->GetNativeView();
109 // Overridden from views::View:
110 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
111 mouse_presses_++;
112 return false;
115 int mouse_presses() const { return mouse_presses_; }
116 private:
117 int mouse_presses_;
119 DISALLOW_COPY_AND_ASSIGN(EventTestWindow);
122 class TransientWindowObserver : public aura::WindowObserver {
123 public:
124 TransientWindowObserver() : destroyed_(false) {}
125 virtual ~TransientWindowObserver() {}
127 bool destroyed() const { return destroyed_; }
129 // Overridden from aura::WindowObserver:
130 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
131 destroyed_ = true;
134 private:
135 bool destroyed_;
137 DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
140 } // namespace
142 class SystemModalContainerLayoutManagerTest : public AshTestBase {
143 public:
144 aura::Window* OpenToplevelTestWindow(bool modal) {
145 views::Widget* widget = views::Widget::CreateWindowWithContext(
146 new TestWindow(modal), CurrentContext());
147 widget->Show();
148 return widget->GetNativeView();
151 aura::Window* OpenTestWindowWithParent(aura::Window* parent, bool modal) {
152 views::Widget* widget =
153 views::Widget::CreateWindowWithParent(new TestWindow(modal), parent);
154 widget->Show();
155 return widget->GetNativeView();
159 TEST_F(SystemModalContainerLayoutManagerTest, NonModalTransient) {
160 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
161 aura::Window* transient = OpenTestWindowWithParent(parent.get(), false);
162 TransientWindowObserver destruction_observer;
163 transient->AddObserver(&destruction_observer);
165 EXPECT_EQ(parent.get(), views::corewm::GetTransientParent(transient));
166 EXPECT_EQ(parent->parent(), transient->parent());
168 // The transient should be destroyed with its parent.
169 parent.reset();
170 EXPECT_TRUE(destruction_observer.destroyed());
173 TEST_F(SystemModalContainerLayoutManagerTest, ModalTransient) {
174 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
175 // parent should be active.
176 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
177 aura::Window* t1 = OpenTestWindowWithParent(parent.get(), true);
179 TransientWindowObserver do1;
180 t1->AddObserver(&do1);
182 EXPECT_EQ(parent.get(), views::corewm::GetTransientParent(t1));
183 EXPECT_EQ(GetModalContainer(), t1->parent());
185 // t1 should now be active.
186 EXPECT_TRUE(wm::IsActiveWindow(t1));
188 // Attempting to click the parent should result in no activation change.
189 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
190 e1.ClickLeftButton();
191 EXPECT_TRUE(wm::IsActiveWindow(t1));
193 // Now open another modal transient parented to the original modal transient.
194 aura::Window* t2 = OpenTestWindowWithParent(t1, true);
195 TransientWindowObserver do2;
196 t2->AddObserver(&do2);
198 EXPECT_TRUE(wm::IsActiveWindow(t2));
200 EXPECT_EQ(t1, views::corewm::GetTransientParent(t2));
201 EXPECT_EQ(GetModalContainer(), t2->parent());
203 // t2 should still be active, even after clicking on t1.
204 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1);
205 e2.ClickLeftButton();
206 EXPECT_TRUE(wm::IsActiveWindow(t2));
208 // Both transients should be destroyed with parent.
209 parent.reset();
210 EXPECT_TRUE(do1.destroyed());
211 EXPECT_TRUE(do2.destroyed());
214 TEST_F(SystemModalContainerLayoutManagerTest, ModalNonTransient) {
215 scoped_ptr<aura::Window> t1(OpenToplevelTestWindow(true));
216 // parent should be active.
217 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
218 TransientWindowObserver do1;
219 t1->AddObserver(&do1);
221 EXPECT_EQ(NULL, views::corewm::GetTransientParent(t1.get()));
222 EXPECT_EQ(GetModalContainer(), t1->parent());
224 // t1 should now be active.
225 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
227 // Attempting to click the parent should result in no activation change.
228 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(),
229 Shell::GetPrimaryRootWindow());
230 e1.ClickLeftButton();
231 EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
233 // Now open another modal transient parented to the original modal transient.
234 aura::Window* t2 = OpenTestWindowWithParent(t1.get(), true);
235 TransientWindowObserver do2;
236 t2->AddObserver(&do2);
238 EXPECT_TRUE(wm::IsActiveWindow(t2));
240 EXPECT_EQ(t1, views::corewm::GetTransientParent(t2));
241 EXPECT_EQ(GetModalContainer(), t2->parent());
243 // t2 should still be active, even after clicking on t1.
244 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1.get());
245 e2.ClickLeftButton();
246 EXPECT_TRUE(wm::IsActiveWindow(t2));
248 // Both transients should be destroyed with parent.
249 t1.reset();
250 EXPECT_TRUE(do1.destroyed());
251 EXPECT_TRUE(do2.destroyed());
254 // Tests that we can activate an unrelated window after a modal window is closed
255 // for a window.
256 TEST_F(SystemModalContainerLayoutManagerTest, CanActivateAfterEndModalSession) {
257 scoped_ptr<aura::Window> unrelated(OpenToplevelTestWindow(false));
258 unrelated->SetBounds(gfx::Rect(100, 100, 50, 50));
259 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
260 // parent should be active.
261 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
263 scoped_ptr<aura::Window> transient(
264 OpenTestWindowWithParent(parent.get(), true));
265 // t1 should now be active.
266 EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
268 // Attempting to click the parent should result in no activation change.
269 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
270 e1.ClickLeftButton();
271 EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
273 // Now close the transient.
274 transient->Hide();
275 TestWindow::CloseTestWindow(transient.release());
277 base::RunLoop().RunUntilIdle();
279 // parent should now be active again.
280 EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
282 // Attempting to click unrelated should activate it.
283 aura::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), unrelated.get());
284 e2.ClickLeftButton();
285 EXPECT_TRUE(wm::IsActiveWindow(unrelated.get()));
288 TEST_F(SystemModalContainerLayoutManagerTest, EventFocusContainers) {
289 // Create a normal window and attempt to receive a click event.
290 EventTestWindow* main_delegate = new EventTestWindow(false);
291 scoped_ptr<aura::Window> main(
292 main_delegate->OpenTestWindowWithContext(CurrentContext()));
293 EXPECT_TRUE(wm::IsActiveWindow(main.get()));
294 aura::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), main.get());
295 e1.ClickLeftButton();
296 EXPECT_EQ(1, main_delegate->mouse_presses());
298 // Create a modal window for the main window and verify that the main window
299 // no longer receives mouse events.
300 EventTestWindow* transient_delegate = new EventTestWindow(true);
301 aura::Window* transient =
302 transient_delegate->OpenTestWindowWithParent(main.get());
303 EXPECT_TRUE(wm::IsActiveWindow(transient));
304 e1.ClickLeftButton();
305 EXPECT_EQ(1, transient_delegate->mouse_presses());
307 for (int block_reason = FIRST_BLOCK_REASON;
308 block_reason < NUMBER_OF_BLOCK_REASONS;
309 ++block_reason) {
310 // Create a window in the lock screen container and ensure that it receives
311 // the mouse event instead of the modal window (crbug.com/110920).
312 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
313 EventTestWindow* lock_delegate = new EventTestWindow(false);
314 scoped_ptr<aura::Window> lock(lock_delegate->OpenTestWindowWithParent(
315 Shell::GetPrimaryRootWindowController()->GetContainer(
316 ash::internal::kShellWindowId_LockScreenContainer)));
317 EXPECT_TRUE(wm::IsActiveWindow(lock.get()));
318 e1.ClickLeftButton();
319 EXPECT_EQ(1, lock_delegate->mouse_presses());
321 // Make sure that a modal container created by the lock screen can still
322 // receive mouse events.
323 EventTestWindow* lock_modal_delegate = new EventTestWindow(true);
324 aura::Window* lock_modal =
325 lock_modal_delegate->OpenTestWindowWithParent(lock.get());
326 EXPECT_TRUE(wm::IsActiveWindow(lock_modal));
327 e1.ClickLeftButton();
328 // Verify that none of the other containers received any more mouse presses.
329 EXPECT_EQ(1, lock_modal_delegate->mouse_presses());
330 EXPECT_EQ(1, lock_delegate->mouse_presses());
331 EXPECT_EQ(1, main_delegate->mouse_presses());
332 EXPECT_EQ(1, transient_delegate->mouse_presses());
333 UnblockUserSession();
337 // Makes sure we don't crash if a modal window is shown while the parent window
338 // is hidden.
339 TEST_F(SystemModalContainerLayoutManagerTest, ShowModalWhileHidden) {
340 // Hide the lock screen.
341 Shell::GetPrimaryRootWindowController()->GetContainer(
342 internal::kShellWindowId_SystemModalContainer)->layer()->SetOpacity(0);
344 // Create a modal window.
345 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
346 scoped_ptr<aura::Window> modal_window(
347 OpenTestWindowWithParent(parent.get(), true));
348 parent->Show();
349 modal_window->Show();
352 // Verifies we generate a capture lost when showing a modal window.
353 TEST_F(SystemModalContainerLayoutManagerTest, ChangeCapture) {
354 views::Widget* widget = views::Widget::CreateWindowWithContext(
355 new TestWindow(false), CurrentContext());
356 scoped_ptr<aura::Window> widget_window(widget->GetNativeView());
357 views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView;
358 widget->GetContentsView()->AddChildView(view);
359 view->SetBoundsRect(widget->GetContentsView()->bounds());
360 widget->Show();
362 gfx::Point center(view->width() / 2, view->height() / 2);
363 views::View::ConvertPointToScreen(view, &center);
364 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center);
365 generator.PressLeftButton();
366 EXPECT_TRUE(view->got_press());
367 scoped_ptr<aura::Window> modal_window(
368 OpenTestWindowWithParent(widget->GetNativeView(), true));
369 modal_window->Show();
370 EXPECT_TRUE(view->got_capture_lost());
373 // Verifies that the window gets moved into the visible screen area upon screen
374 // resize.
375 TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) {
376 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768));
377 scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(),
378 true));
379 main->SetBounds(gfx::Rect(924, 668, 100, 100));
380 // We set now the bounds of the root window to something new which will
381 // Then trigger the repos operation.
382 GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600));
384 gfx::Rect bounds = main->bounds();
385 EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100));
388 TEST_F(SystemModalContainerLayoutManagerTest, ShowNormalBackgroundOrLocked) {
389 scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
390 scoped_ptr<aura::Window> modal_window(
391 OpenTestWindowWithParent(parent.get(), true));
392 parent->Show();
393 modal_window->Show();
395 // Normal system modal window. Shows normal system modal background and not
396 // locked.
397 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
398 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
400 TestWindow::CloseTestWindow(modal_window.release());
401 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
402 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
404 for (int block_reason = FIRST_BLOCK_REASON;
405 block_reason < NUMBER_OF_BLOCK_REASONS;
406 ++block_reason) {
407 // Normal system modal window while blocked. Shows blocked system modal
408 // background.
409 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
410 scoped_ptr<aura::Window> lock_parent(OpenTestWindowWithParent(
411 Shell::GetPrimaryRootWindowController()->GetContainer(
412 ash::internal::kShellWindowId_LockScreenContainer),
413 false));
414 scoped_ptr<aura::Window> lock_modal_window(OpenTestWindowWithParent(
415 lock_parent.get(), true));
416 lock_parent->Show();
417 lock_modal_window->Show();
418 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
419 EXPECT_TRUE(AllRootWindowsHaveLockedModalBackgrounds());
420 TestWindow::CloseTestWindow(lock_modal_window.release());
422 // Normal system modal window while blocked, but it belongs to the normal
423 // window. Shouldn't show blocked system modal background, but normal.
424 scoped_ptr<aura::Window> modal_window(
425 OpenTestWindowWithParent(parent.get(), true));
426 modal_window->Show();
427 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
428 EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
429 TestWindow::CloseTestWindow(modal_window.release());
430 UnblockUserSession();
431 // Here we should check the behavior of the locked system modal dialog when
432 // unlocked, but such case isn't handled very well right now.
433 // See crbug.com/157660
434 // TODO(mukai): add the test case when the bug is fixed.
438 TEST_F(SystemModalContainerLayoutManagerTest, MultiDisplays) {
439 if (!SupportsMultipleDisplays())
440 return;
442 UpdateDisplay("500x500,500x500");
444 scoped_ptr<aura::Window> normal(OpenToplevelTestWindow(false));
445 normal->SetBounds(gfx::Rect(100, 100, 50, 50));
447 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
448 EXPECT_EQ(2U, root_windows.size());
449 aura::Window* container1 = Shell::GetContainer(
450 root_windows[0], ash::internal::kShellWindowId_SystemModalContainer);
451 aura::Window* container2 = Shell::GetContainer(
452 root_windows[1], ash::internal::kShellWindowId_SystemModalContainer);
454 scoped_ptr<aura::Window> modal1(
455 OpenTestWindowWithParent(container1, true));
456 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
457 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
459 scoped_ptr<aura::Window> modal11(
460 OpenTestWindowWithParent(container1, true));
461 EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
463 scoped_ptr<aura::Window> modal2(
464 OpenTestWindowWithParent(container2, true));
465 EXPECT_TRUE(wm::IsActiveWindow(modal2.get()));
467 // Sanity check if they're on the correct containers.
468 EXPECT_EQ(container1, modal1->parent());
469 EXPECT_EQ(container1, modal11->parent());
470 EXPECT_EQ(container2, modal2->parent());
472 TestWindow::CloseTestWindow(modal2.release());
473 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
474 EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
476 TestWindow::CloseTestWindow(modal11.release());
477 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
478 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
480 UpdateDisplay("500x500");
481 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
482 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
484 UpdateDisplay("500x500,600x600");
485 EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
486 EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
488 // No more modal screen.
489 modal1->Hide();
490 TestWindow::CloseTestWindow(modal1.release());
491 EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
492 EXPECT_TRUE(wm::IsActiveWindow(normal.get()));
495 } // namespace test
496 } // namespace ash