Reland Double-Click on a Tab Close causes Maximize
[chromium-blink-merge.git] / ash / root_window_controller_unittest.cc
blob69aad6b7d4f9f9b1520813933fdf2611e598bb62
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/root_window_controller.h"
7 #include "ash/session_state_delegate.h"
8 #include "ash/shelf/shelf_layout_manager.h"
9 #include "ash/shell.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/system/tray/system_tray_delegate.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/wm/system_modal_container_layout_manager.h"
14 #include "ash/wm/window_properties.h"
15 #include "ash/wm/window_state.h"
16 #include "ash/wm/window_util.h"
17 #include "base/command_line.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/focus_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/env.h"
22 #include "ui/aura/test/event_generator.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/window.h"
26 #include "ui/aura/window_event_dispatcher.h"
27 #include "ui/aura/window_tracker.h"
28 #include "ui/events/test/test_event_handler.h"
29 #include "ui/keyboard/keyboard_controller_proxy.h"
30 #include "ui/keyboard/keyboard_switches.h"
31 #include "ui/views/controls/menu/menu_controller.h"
32 #include "ui/views/widget/widget.h"
33 #include "ui/views/widget/widget_delegate.h"
35 using aura::Window;
36 using views::Widget;
38 namespace ash {
39 namespace {
41 class TestDelegate : public views::WidgetDelegateView {
42 public:
43 explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {}
44 virtual ~TestDelegate() {}
46 // Overridden from views::WidgetDelegate:
47 virtual views::View* GetContentsView() OVERRIDE {
48 return this;
51 virtual ui::ModalType GetModalType() const OVERRIDE {
52 return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
55 private:
56 bool system_modal_;
58 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
61 class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate,
62 public aura::client::FocusChangeObserver {
63 public:
64 DeleteOnBlurDelegate() : window_(NULL) {}
65 virtual ~DeleteOnBlurDelegate() {}
67 void SetWindow(aura::Window* window) {
68 window_ = window;
69 aura::client::SetFocusChangeObserver(window_, this);
72 private:
73 // aura::test::TestWindowDelegate overrides:
74 virtual bool CanFocus() OVERRIDE {
75 return true;
78 // aura::client::FocusChangeObserver implementation:
79 virtual void OnWindowFocused(aura::Window* gained_focus,
80 aura::Window* lost_focus) OVERRIDE {
81 if (window_ == lost_focus)
82 delete window_;
85 aura::Window* window_;
87 DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate);
90 } // namespace
92 namespace test {
94 class RootWindowControllerTest : public test::AshTestBase {
95 public:
96 views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
97 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
98 NULL, CurrentContext(), bounds);
99 widget->Show();
100 return widget;
103 views::Widget* CreateModalWidget(const gfx::Rect& bounds) {
104 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
105 new TestDelegate(true), CurrentContext(), bounds);
106 widget->Show();
107 return widget;
110 views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds,
111 gfx::NativeWindow parent) {
112 views::Widget* widget =
113 views::Widget::CreateWindowWithParentAndBounds(new TestDelegate(true),
114 parent,
115 bounds);
116 widget->Show();
117 return widget;
120 aura::Window* GetModalContainer(aura::Window* root_window) {
121 return Shell::GetContainer(root_window,
122 ash::kShellWindowId_SystemModalContainer);
126 TEST_F(RootWindowControllerTest, MoveWindows_Basic) {
127 if (!SupportsMultipleDisplays())
128 return;
129 // Windows origin should be doubled when moved to the 1st display.
130 UpdateDisplay("600x600,300x300");
131 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
132 RootWindowController* controller = Shell::GetPrimaryRootWindowController();
133 ShelfLayoutManager* shelf_layout_manager =
134 controller->GetShelfLayoutManager();
135 shelf_layout_manager->SetAutoHideBehavior(
136 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
138 views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100));
139 EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow());
140 EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString());
141 EXPECT_EQ("50,10 100x100",
142 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
144 views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100));
145 maximized->Maximize();
146 EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow());
147 EXPECT_EQ("600,0 300x253", maximized->GetWindowBoundsInScreen().ToString());
148 EXPECT_EQ("0,0 300x253",
149 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
151 views::Widget* minimized = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
152 minimized->Minimize();
153 EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow());
154 EXPECT_EQ("800,10 100x100",
155 minimized->GetWindowBoundsInScreen().ToString());
157 views::Widget* fullscreen = CreateTestWidget(gfx::Rect(850, 10, 100, 100));
158 fullscreen->SetFullscreen(true);
159 EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow());
161 EXPECT_EQ("600,0 300x300",
162 fullscreen->GetWindowBoundsInScreen().ToString());
163 EXPECT_EQ("0,0 300x300",
164 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
166 views::Widget* unparented_control = new Widget;
167 Widget::InitParams params;
168 params.bounds = gfx::Rect(650, 10, 100, 100);
169 params.context = CurrentContext();
170 params.type = Widget::InitParams::TYPE_CONTROL;
171 unparented_control->Init(params);
172 EXPECT_EQ(root_windows[1],
173 unparented_control->GetNativeView()->GetRootWindow());
174 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
175 unparented_control->GetNativeView()->parent()->id());
177 aura::Window* panel = CreateTestWindowInShellWithDelegateAndType(
178 NULL, ui::wm::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100));
179 EXPECT_EQ(root_windows[1], panel->GetRootWindow());
180 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
182 // Make sure a window that will delete itself when losing focus
183 // will not crash.
184 aura::WindowTracker tracker;
185 DeleteOnBlurDelegate delete_on_blur_delegate;
186 aura::Window* d2 = CreateTestWindowInShellWithDelegate(
187 &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100));
188 delete_on_blur_delegate.SetWindow(d2);
189 aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2);
190 tracker.Add(d2);
192 UpdateDisplay("600x600");
194 // d2 must have been deleted.
195 EXPECT_FALSE(tracker.Contains(d2));
197 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
198 EXPECT_EQ("100,20 100x100", normal->GetWindowBoundsInScreen().ToString());
199 EXPECT_EQ("100,20 100x100",
200 normal->GetNativeView()->GetBoundsInRootWindow().ToString());
202 // Maximized area on primary display has 3px (given as
203 // kAutoHideSize in shelf_layout_manager.cc) inset at the bottom.
205 // First clear fullscreen status, since both fullscreen and maximized windows
206 // share the same desktop workspace, which cancels the shelf status.
207 fullscreen->SetFullscreen(false);
208 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
209 EXPECT_EQ("0,0 600x597",
210 maximized->GetWindowBoundsInScreen().ToString());
211 EXPECT_EQ("0,0 600x597",
212 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
214 // Set fullscreen to true. In that case the 3px inset becomes invisible so
215 // the maximized window can also use the area fully.
216 fullscreen->SetFullscreen(true);
217 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
218 EXPECT_EQ("0,0 600x600",
219 maximized->GetWindowBoundsInScreen().ToString());
220 EXPECT_EQ("0,0 600x600",
221 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
223 EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow());
224 EXPECT_EQ("400,20 100x100",
225 minimized->GetWindowBoundsInScreen().ToString());
227 EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow());
228 EXPECT_TRUE(fullscreen->IsFullscreen());
229 EXPECT_EQ("0,0 600x600",
230 fullscreen->GetWindowBoundsInScreen().ToString());
231 EXPECT_EQ("0,0 600x600",
232 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
234 // Test if the restore bounds are correctly updated.
235 wm::GetWindowState(maximized->GetNativeView())->Restore();
236 EXPECT_EQ("200,20 100x100", maximized->GetWindowBoundsInScreen().ToString());
237 EXPECT_EQ("200,20 100x100",
238 maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
240 fullscreen->SetFullscreen(false);
241 EXPECT_EQ("500,20 100x100",
242 fullscreen->GetWindowBoundsInScreen().ToString());
243 EXPECT_EQ("500,20 100x100",
244 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
246 // Test if the unparented widget has moved.
247 EXPECT_EQ(root_windows[0],
248 unparented_control->GetNativeView()->GetRootWindow());
249 EXPECT_EQ(kShellWindowId_UnparentedControlContainer,
250 unparented_control->GetNativeView()->parent()->id());
252 // Test if the panel has moved.
253 EXPECT_EQ(root_windows[0], panel->GetRootWindow());
254 EXPECT_EQ(kShellWindowId_PanelContainer, panel->parent()->id());
257 TEST_F(RootWindowControllerTest, MoveWindows_Modal) {
258 if (!SupportsMultipleDisplays())
259 return;
261 UpdateDisplay("500x500,500x500");
263 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
264 // Emulate virtual screen coordinate system.
265 root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500));
266 root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500));
268 views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100));
269 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
270 EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView()));
272 views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100));
273 EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow());
274 EXPECT_TRUE(GetModalContainer(root_windows[1])->Contains(
275 modal->GetNativeView()));
276 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
278 aura::test::EventGenerator generator_1st(root_windows[0]);
279 generator_1st.ClickLeftButton();
280 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
282 UpdateDisplay("500x500");
283 EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow());
284 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
285 generator_1st.ClickLeftButton();
286 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
289 TEST_F(RootWindowControllerTest, ModalContainer) {
290 UpdateDisplay("600x600");
291 Shell* shell = Shell::GetInstance();
292 RootWindowController* controller = shell->GetPrimaryRootWindowController();
293 EXPECT_EQ(user::LOGGED_IN_USER,
294 shell->system_tray_delegate()->GetUserLoginStatus());
295 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
296 ->layout_manager(),
297 controller->GetSystemModalLayoutManager(NULL));
299 views::Widget* session_modal_widget =
300 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
301 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
302 ->layout_manager(),
303 controller->GetSystemModalLayoutManager(
304 session_modal_widget->GetNativeView()));
306 shell->session_state_delegate()->LockScreen();
307 EXPECT_EQ(user::LOGGED_IN_LOCKED,
308 shell->system_tray_delegate()->GetUserLoginStatus());
309 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
310 ->layout_manager(),
311 controller->GetSystemModalLayoutManager(NULL));
313 aura::Window* lock_container =
314 controller->GetContainer(kShellWindowId_LockScreenContainer);
315 views::Widget* lock_modal_widget =
316 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
317 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
318 ->layout_manager(),
319 controller->GetSystemModalLayoutManager(
320 lock_modal_widget->GetNativeView()));
321 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
322 ->layout_manager(),
323 controller->GetSystemModalLayoutManager(
324 session_modal_widget->GetNativeView()));
326 shell->session_state_delegate()->UnlockScreen();
329 TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
330 UpdateDisplay("600x600");
331 Shell* shell = Shell::GetInstance();
333 // Configure login screen environment.
334 SetUserLoggedIn(false);
335 EXPECT_EQ(user::LOGGED_IN_NONE,
336 shell->system_tray_delegate()->GetUserLoginStatus());
337 EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers());
338 EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted());
340 RootWindowController* controller = shell->GetPrimaryRootWindowController();
341 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
342 ->layout_manager(),
343 controller->GetSystemModalLayoutManager(NULL));
345 aura::Window* lock_container =
346 controller->GetContainer(kShellWindowId_LockScreenContainer);
347 views::Widget* login_modal_widget =
348 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
349 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
350 ->layout_manager(),
351 controller->GetSystemModalLayoutManager(
352 login_modal_widget->GetNativeView()));
353 login_modal_widget->Close();
355 // Configure user session environment.
356 SetUserLoggedIn(true);
357 SetSessionStarted(true);
358 EXPECT_EQ(user::LOGGED_IN_USER,
359 shell->system_tray_delegate()->GetUserLoginStatus());
360 EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers());
361 EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted());
362 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
363 ->layout_manager(),
364 controller->GetSystemModalLayoutManager(NULL));
366 views::Widget* session_modal_widget =
367 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
368 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
369 ->layout_manager(),
370 controller->GetSystemModalLayoutManager(
371 session_modal_widget->GetNativeView()));
374 TEST_F(RootWindowControllerTest, ModalContainerBlockedSession) {
375 UpdateDisplay("600x600");
376 Shell* shell = Shell::GetInstance();
377 RootWindowController* controller = shell->GetPrimaryRootWindowController();
378 aura::Window* lock_container =
379 controller->GetContainer(kShellWindowId_LockScreenContainer);
380 for (int block_reason = FIRST_BLOCK_REASON;
381 block_reason < NUMBER_OF_BLOCK_REASONS;
382 ++block_reason) {
383 views::Widget* session_modal_widget =
384 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
385 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
386 ->layout_manager(),
387 controller->GetSystemModalLayoutManager(
388 session_modal_widget->GetNativeView()));
389 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
390 ->layout_manager(),
391 controller->GetSystemModalLayoutManager(NULL));
392 session_modal_widget->Close();
394 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
396 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
397 ->layout_manager(),
398 controller->GetSystemModalLayoutManager(NULL));
400 views::Widget* lock_modal_widget =
401 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100),
402 lock_container);
403 EXPECT_EQ(controller->GetContainer(kShellWindowId_LockSystemModalContainer)
404 ->layout_manager(),
405 controller->GetSystemModalLayoutManager(
406 lock_modal_widget->GetNativeView()));
408 session_modal_widget =
409 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
410 EXPECT_EQ(controller->GetContainer(kShellWindowId_SystemModalContainer)
411 ->layout_manager(),
412 controller->GetSystemModalLayoutManager(
413 session_modal_widget->GetNativeView()));
414 session_modal_widget->Close();
416 lock_modal_widget->Close();
417 UnblockUserSession();
421 TEST_F(RootWindowControllerTest, GetWindowForFullscreenMode) {
422 UpdateDisplay("600x600");
423 RootWindowController* controller =
424 Shell::GetInstance()->GetPrimaryRootWindowController();
426 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
427 w1->Maximize();
428 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
429 w2->SetFullscreen(true);
430 // |w3| is a transient child of |w2|.
431 Widget* w3 = Widget::CreateWindowWithParentAndBounds(NULL,
432 w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
434 // Test that GetWindowForFullscreenMode() finds the fullscreen window when one
435 // of its transient children is active.
436 w3->Activate();
437 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
439 // If the topmost window is not fullscreen, it returns NULL.
440 w1->Activate();
441 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
442 w1->Close();
443 w3->Close();
445 // Only w2 remains, if minimized GetWindowForFullscreenMode should return
446 // NULL.
447 w2->Activate();
448 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode());
449 w2->Minimize();
450 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode());
453 TEST_F(RootWindowControllerTest, MultipleDisplaysGetWindowForFullscreenMode) {
454 if (!SupportsMultipleDisplays())
455 return;
457 UpdateDisplay("600x600,600x600");
458 Shell::RootWindowControllerList controllers =
459 Shell::GetInstance()->GetAllRootWindowControllers();
461 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
462 w1->Maximize();
463 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
464 w2->SetFullscreen(true);
465 Widget* w3 = CreateTestWidget(gfx::Rect(600, 0, 100, 100));
467 EXPECT_EQ(w1->GetNativeWindow()->GetRootWindow(),
468 controllers[0]->GetRootWindow());
469 EXPECT_EQ(w2->GetNativeWindow()->GetRootWindow(),
470 controllers[0]->GetRootWindow());
471 EXPECT_EQ(w3->GetNativeWindow()->GetRootWindow(),
472 controllers[1]->GetRootWindow());
474 w1->Activate();
475 EXPECT_EQ(NULL, controllers[0]->GetWindowForFullscreenMode());
476 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
478 w2->Activate();
479 EXPECT_EQ(w2->GetNativeWindow(),
480 controllers[0]->GetWindowForFullscreenMode());
481 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
483 // Verify that the first root window controller remains in fullscreen mode
484 // when a window on the other display is activated.
485 w3->Activate();
486 EXPECT_EQ(w2->GetNativeWindow(),
487 controllers[0]->GetWindowForFullscreenMode());
488 EXPECT_EQ(NULL, controllers[1]->GetWindowForFullscreenMode());
491 // Test that user session window can't be focused if user session blocked by
492 // some overlapping UI.
493 TEST_F(RootWindowControllerTest, FocusBlockedWindow) {
494 UpdateDisplay("600x600");
495 RootWindowController* controller =
496 Shell::GetInstance()->GetPrimaryRootWindowController();
497 aura::Window* lock_container =
498 controller->GetContainer(kShellWindowId_LockScreenContainer);
499 aura::Window* lock_window = Widget::CreateWindowWithParentAndBounds(NULL,
500 lock_container, gfx::Rect(0, 0, 100, 100))->GetNativeView();
501 lock_window->Show();
502 aura::Window* session_window =
503 CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView();
504 session_window->Show();
506 for (int block_reason = FIRST_BLOCK_REASON;
507 block_reason < NUMBER_OF_BLOCK_REASONS;
508 ++block_reason) {
509 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
510 lock_window->Focus();
511 EXPECT_TRUE(lock_window->HasFocus());
512 session_window->Focus();
513 EXPECT_FALSE(session_window->HasFocus());
514 UnblockUserSession();
518 // Tracks whether OnWindowDestroying() has been invoked.
519 class DestroyedWindowObserver : public aura::WindowObserver {
520 public:
521 DestroyedWindowObserver() : destroyed_(false), window_(NULL) {}
522 virtual ~DestroyedWindowObserver() {
523 Shutdown();
526 void SetWindow(Window* window) {
527 window_ = window;
528 window->AddObserver(this);
531 bool destroyed() const { return destroyed_; }
533 // WindowObserver overrides:
534 virtual void OnWindowDestroying(Window* window) OVERRIDE {
535 destroyed_ = true;
536 Shutdown();
539 private:
540 void Shutdown() {
541 if (!window_)
542 return;
543 window_->RemoveObserver(this);
544 window_ = NULL;
547 bool destroyed_;
548 Window* window_;
550 DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver);
553 // Verifies shutdown doesn't delete windows that are not owned by the parent.
554 TEST_F(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) {
555 DestroyedWindowObserver observer1;
556 aura::test::TestWindowDelegate delegate1;
557 aura::Window* window1 = new aura::Window(&delegate1);
558 window1->SetType(ui::wm::WINDOW_TYPE_CONTROL);
559 window1->set_owned_by_parent(false);
560 observer1.SetWindow(window1);
561 window1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
562 aura::client::ParentWindowWithContext(
563 window1, Shell::GetInstance()->GetPrimaryRootWindow(), gfx::Rect());
565 DestroyedWindowObserver observer2;
566 aura::Window* window2 = new aura::Window(NULL);
567 window2->set_owned_by_parent(false);
568 observer2.SetWindow(window2);
569 window2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
570 Shell::GetInstance()->GetPrimaryRootWindow()->AddChild(window2);
572 Shell::GetInstance()->GetPrimaryRootWindowController()->CloseChildWindows();
574 ASSERT_FALSE(observer1.destroyed());
575 delete window1;
577 ASSERT_FALSE(observer2.destroyed());
578 delete window2;
581 typedef test::NoSessionAshTestBase NoSessionRootWindowControllerTest;
583 // Make sure that an event handler exists for entire display area.
584 TEST_F(NoSessionRootWindowControllerTest, Event) {
585 aura::Window* root = Shell::GetPrimaryRootWindow();
586 const gfx::Size size = root->bounds().size();
587 aura::Window* event_target = root->GetEventHandlerForPoint(gfx::Point(0, 0));
588 EXPECT_TRUE(event_target);
589 EXPECT_EQ(event_target,
590 root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
591 EXPECT_EQ(event_target,
592 root->GetEventHandlerForPoint(gfx::Point(size.width() - 1, 0)));
593 EXPECT_EQ(event_target,
594 root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
595 EXPECT_EQ(event_target,
596 root->GetEventHandlerForPoint(
597 gfx::Point(size.width() - 1, size.height() - 1)));
600 class VirtualKeyboardRootWindowControllerTest : public RootWindowControllerTest
602 public:
603 VirtualKeyboardRootWindowControllerTest() {};
604 virtual ~VirtualKeyboardRootWindowControllerTest() {};
606 virtual void SetUp() OVERRIDE {
607 CommandLine::ForCurrentProcess()->AppendSwitch(
608 keyboard::switches::kEnableVirtualKeyboard);
609 test::AshTestBase::SetUp();
610 Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
611 keyboard::KeyboardController::GetInstance());
614 private:
615 DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest);
618 // Test for http://crbug.com/297858. Virtual keyboard container should only show
619 // on primary root window.
620 TEST_F(VirtualKeyboardRootWindowControllerTest,
621 VirtualKeyboardOnPrimaryRootWindowOnly) {
622 if (!SupportsMultipleDisplays())
623 return;
625 UpdateDisplay("500x500,500x500");
627 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
628 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
629 aura::Window* secondary_root_window =
630 root_windows[0] == primary_root_window ?
631 root_windows[1] : root_windows[0];
633 ASSERT_TRUE(Shell::GetContainer(primary_root_window,
634 kShellWindowId_VirtualKeyboardContainer));
635 ASSERT_FALSE(Shell::GetContainer(secondary_root_window,
636 kShellWindowId_VirtualKeyboardContainer));
639 // Test for http://crbug.com/263599. Virtual keyboard should be able to receive
640 // events at blocked user session.
641 TEST_F(VirtualKeyboardRootWindowControllerTest,
642 ClickVirtualKeyboardInBlockedWindow) {
643 aura::Window* root_window = Shell::GetPrimaryRootWindow();
644 aura::Window* keyboard_container =
645 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
646 ASSERT_TRUE(keyboard_container);
647 keyboard_container->Show();
649 aura::Window* keyboard_window = keyboard::KeyboardController::GetInstance()->
650 proxy()->GetKeyboardWindow();
651 keyboard_container->AddChild(keyboard_window);
652 keyboard_window->set_owned_by_parent(false);
653 keyboard_window->SetBounds(gfx::Rect());
654 keyboard_window->Show();
656 ui::test::TestEventHandler* handler = new ui::test::TestEventHandler;
657 root_window->SetEventFilter(handler);
659 aura::test::EventGenerator event_generator(root_window, keyboard_window);
660 event_generator.ClickLeftButton();
661 int expected_mouse_presses = 1;
662 EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2);
664 for (int block_reason = FIRST_BLOCK_REASON;
665 block_reason < NUMBER_OF_BLOCK_REASONS;
666 ++block_reason) {
667 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
668 event_generator.ClickLeftButton();
669 expected_mouse_presses++;
670 EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2);
671 UnblockUserSession();
675 // Test for http://crbug.com/299787. RootWindowController should delete
676 // the old container since the keyboard controller creates a new window in
677 // GetWindowContainer().
678 TEST_F(VirtualKeyboardRootWindowControllerTest,
679 DeleteOldContainerOnVirtualKeyboardInit) {
680 aura::Window* root_window = Shell::GetPrimaryRootWindow();
681 aura::Window* keyboard_container =
682 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
683 ASSERT_TRUE(keyboard_container);
684 // Track the keyboard container window.
685 aura::WindowTracker tracker;
686 tracker.Add(keyboard_container);
687 // Mock a login user profile change to reinitialize the keyboard.
688 ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
689 // keyboard_container should no longer be present.
690 EXPECT_FALSE(tracker.Contains(keyboard_container));
693 // Test for crbug.com/342524. After user login, the work space should restore to
694 // full screen.
695 TEST_F(VirtualKeyboardRootWindowControllerTest, RestoreWorkspaceAfterLogin) {
696 aura::Window* root_window = Shell::GetPrimaryRootWindow();
697 aura::Window* keyboard_container =
698 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
699 keyboard_container->Show();
700 keyboard::KeyboardController* controller =
701 keyboard::KeyboardController::GetInstance();
702 aura::Window* keyboard_window = controller->proxy()->GetKeyboardWindow();
703 keyboard_container->AddChild(keyboard_window);
704 keyboard_window->set_owned_by_parent(false);
705 keyboard_window->Show();
707 gfx::Rect before = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
709 // Notify keyboard bounds changing.
710 controller->NotifyKeyboardBoundsChanging(
711 controller->proxy()->GetKeyboardWindow()->bounds());
713 gfx::Rect after = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
714 EXPECT_LT(after, before);
716 // Mock a login user profile change to reinitialize the keyboard.
717 ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
718 EXPECT_EQ(ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(), before);
721 // Ensure that system modal dialogs do not block events targeted at the virtual
722 // keyboard.
723 TEST_F(VirtualKeyboardRootWindowControllerTest, ClickWithActiveModalDialog) {
724 aura::Window* root_window = Shell::GetPrimaryRootWindow();
725 aura::Window* keyboard_container =
726 Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer);
727 ASSERT_TRUE(keyboard_container);
728 keyboard_container->Show();
730 aura::Window* keyboard_window = keyboard::KeyboardController::GetInstance()->
731 proxy()->GetKeyboardWindow();
732 keyboard_container->AddChild(keyboard_window);
733 keyboard_window->set_owned_by_parent(false);
734 keyboard_window->SetBounds(gfx::Rect());
735 keyboard_window->Show();
737 ui::test::TestEventHandler* handler = new ui::test::TestEventHandler;
738 root_window->SetEventFilter(handler);
739 aura::test::EventGenerator root_window_event_generator(root_window);
740 aura::test::EventGenerator keyboard_event_generator(root_window,
741 keyboard_window);
743 views::Widget* modal_widget =
744 CreateModalWidget(gfx::Rect(300, 10, 100, 100));
746 // Verify that mouse events to the root window are block with a visble modal
747 // dialog.
748 root_window_event_generator.ClickLeftButton();
749 EXPECT_EQ(0, handler->num_mouse_events());
751 // Verify that event dispatch to the virtual keyboard is unblocked.
752 keyboard_event_generator.ClickLeftButton();
753 EXPECT_EQ(1, handler->num_mouse_events() / 2);
755 modal_widget->Close();
757 // Verify that mouse events are now unblocked to the root window.
758 root_window_event_generator.ClickLeftButton();
759 EXPECT_EQ(2, handler->num_mouse_events() / 2);
762 } // namespace test
763 } // namespace ash