- add sources.
[platform/framework/web/crosswalk.git] / src / ash / root_window_controller_unittest.cc
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.
4
5 #include "ash/root_window_controller.h"
6
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/root_window.h"
23 #include "ui/aura/test/event_generator.h"
24 #include "ui/aura/test/test_window_delegate.h"
25 #include "ui/aura/test/test_windows.h"
26 #include "ui/aura/window.h"
27 #include "ui/aura/window_tracker.h"
28 #include "ui/keyboard/keyboard_switches.h"
29 #include "ui/views/controls/menu/menu_controller.h"
30 #include "ui/views/widget/widget.h"
31 #include "ui/views/widget/widget_delegate.h"
32
33 using aura::Window;
34 using views::Widget;
35
36 namespace ash {
37 namespace {
38
39 class TestDelegate : public views::WidgetDelegateView {
40  public:
41   explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {}
42   virtual ~TestDelegate() {}
43
44   // Overridden from views::WidgetDelegate:
45   virtual views::View* GetContentsView() OVERRIDE {
46     return this;
47   }
48
49   virtual ui::ModalType GetModalType() const OVERRIDE {
50     return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
51   }
52
53  private:
54   bool system_modal_;
55
56   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
57 };
58
59 class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate,
60                              public aura::client::FocusChangeObserver {
61  public:
62   DeleteOnBlurDelegate() : window_(NULL) {}
63   virtual ~DeleteOnBlurDelegate() {}
64
65   void SetWindow(aura::Window* window) {
66     window_ = window;
67     aura::client::SetFocusChangeObserver(window_, this);
68   }
69
70  private:
71   // aura::test::TestWindowDelegate overrides:
72   virtual bool CanFocus() OVERRIDE {
73     return true;
74   }
75
76   // aura::client::FocusChangeObserver implementation:
77   virtual void OnWindowFocused(aura::Window* gained_focus,
78                                aura::Window* lost_focus) OVERRIDE {
79     if (window_ == lost_focus)
80       delete window_;
81   }
82
83   aura::Window* window_;
84
85   DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate);
86 };
87
88 class ClickTestWindow : public views::WidgetDelegateView {
89  public:
90   ClickTestWindow() : mouse_presses_(0) {}
91   virtual ~ClickTestWindow() {}
92
93   // Overridden from views::WidgetDelegate:
94   virtual views::View* GetContentsView() OVERRIDE {
95     return this;
96   }
97
98   aura::Window* CreateTestWindowWithParent(aura::Window* parent) {
99     DCHECK(parent);
100     views::Widget* widget = Widget::CreateWindowWithParent(this, parent);
101     return widget->GetNativeView();
102   }
103
104   // Overridden from views::View:
105   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
106     mouse_presses_++;
107     return false;
108   }
109
110   int mouse_presses() const { return mouse_presses_; }
111
112  private:
113   int mouse_presses_;
114
115   DISALLOW_COPY_AND_ASSIGN(ClickTestWindow);
116 };
117
118 }  // namespace
119
120 namespace test {
121
122 class RootWindowControllerTest : public test::AshTestBase {
123  public:
124   views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
125     views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
126         NULL, CurrentContext(), bounds);
127     widget->Show();
128     return widget;
129   }
130
131   views::Widget* CreateModalWidget(const gfx::Rect& bounds) {
132     views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
133         new TestDelegate(true), CurrentContext(), bounds);
134     widget->Show();
135     return widget;
136   }
137
138   views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds,
139                                              gfx::NativeWindow parent) {
140     views::Widget* widget =
141         views::Widget::CreateWindowWithParentAndBounds(new TestDelegate(true),
142                                                        parent,
143                                                        bounds);
144     widget->Show();
145     return widget;
146   }
147
148   aura::Window* GetModalContainer(aura::RootWindow* root_window) {
149     return Shell::GetContainer(
150         root_window,
151         ash::internal::kShellWindowId_SystemModalContainer);
152   }
153 };
154
155 TEST_F(RootWindowControllerTest, MoveWindows_Basic) {
156   if (!SupportsMultipleDisplays())
157     return;
158
159   UpdateDisplay("600x600,500x500");
160   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
161   internal::RootWindowController* controller =
162       Shell::GetPrimaryRootWindowController();
163   internal::ShelfLayoutManager* shelf_layout_manager =
164       controller->GetShelfLayoutManager();
165   shelf_layout_manager->SetAutoHideBehavior(
166       ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
167
168   views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100));
169   EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow());
170   EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString());
171   EXPECT_EQ("50,10 100x100",
172             normal->GetNativeView()->GetBoundsInRootWindow().ToString());
173
174   views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100));
175   maximized->Maximize();
176   EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow());
177   EXPECT_EQ("600,0 500x453", maximized->GetWindowBoundsInScreen().ToString());
178   EXPECT_EQ("0,0 500x453",
179             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
180
181   views::Widget* minimized = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
182   minimized->Minimize();
183   EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow());
184   EXPECT_EQ("800,10 100x100",
185             minimized->GetWindowBoundsInScreen().ToString());
186
187   views::Widget* fullscreen = CreateTestWidget(gfx::Rect(900, 10, 100, 100));
188   fullscreen->SetFullscreen(true);
189   EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow());
190
191   EXPECT_EQ("600,0 500x500",
192             fullscreen->GetWindowBoundsInScreen().ToString());
193   EXPECT_EQ("0,0 500x500",
194             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
195
196   views::Widget* unparented_control = new Widget;
197   Widget::InitParams params;
198   params.bounds = gfx::Rect(650, 10, 100, 100);
199   params.context = CurrentContext();
200   params.type = Widget::InitParams::TYPE_CONTROL;
201   unparented_control->Init(params);
202   EXPECT_EQ(root_windows[1],
203             unparented_control->GetNativeView()->GetRootWindow());
204   EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer,
205             unparented_control->GetNativeView()->parent()->id());
206
207   aura::Window* panel = CreateTestWindowInShellWithDelegateAndType(
208       NULL, aura::client::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100));
209   EXPECT_EQ(root_windows[1], panel->GetRootWindow());
210   EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id());
211
212   // Make sure a window that will delete itself when losing focus
213   // will not crash.
214   aura::WindowTracker tracker;
215   DeleteOnBlurDelegate delete_on_blur_delegate;
216   aura::Window* d2 = CreateTestWindowInShellWithDelegate(
217       &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100));
218   delete_on_blur_delegate.SetWindow(d2);
219   aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2);
220   tracker.Add(d2);
221
222   UpdateDisplay("600x600");
223
224   // d2 must have been deleted.
225   EXPECT_FALSE(tracker.Contains(d2));
226
227   EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
228   EXPECT_EQ("50,10 100x100", normal->GetWindowBoundsInScreen().ToString());
229   EXPECT_EQ("50,10 100x100",
230             normal->GetNativeView()->GetBoundsInRootWindow().ToString());
231
232   // Maximized area on primary display has 3px (given as
233   // kAutoHideSize in shelf_layout_manager.cc) inset at the bottom.
234
235   // First clear fullscreen status, since both fullscreen and maximized windows
236   // share the same desktop workspace, which cancels the shelf status.
237   fullscreen->SetFullscreen(false);
238   EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
239   EXPECT_EQ("0,0 600x597",
240             maximized->GetWindowBoundsInScreen().ToString());
241   EXPECT_EQ("0,0 600x597",
242             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
243
244   // Set fullscreen to true. In that case the 3px inset becomes invisible so
245   // the maximized window can also use the area fully.
246   fullscreen->SetFullscreen(true);
247   EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow());
248   EXPECT_EQ("0,0 600x600",
249             maximized->GetWindowBoundsInScreen().ToString());
250   EXPECT_EQ("0,0 600x600",
251             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
252
253   EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow());
254   EXPECT_EQ("200,10 100x100",
255             minimized->GetWindowBoundsInScreen().ToString());
256
257   EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow());
258   EXPECT_TRUE(fullscreen->IsFullscreen());
259   EXPECT_EQ("0,0 600x600",
260             fullscreen->GetWindowBoundsInScreen().ToString());
261   EXPECT_EQ("0,0 600x600",
262             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
263
264   // Test if the restore bounds are correctly updated.
265   wm::GetWindowState(maximized->GetNativeView())->Restore();
266   EXPECT_EQ("100,10 100x100", maximized->GetWindowBoundsInScreen().ToString());
267   EXPECT_EQ("100,10 100x100",
268             maximized->GetNativeView()->GetBoundsInRootWindow().ToString());
269
270   fullscreen->SetFullscreen(false);
271   EXPECT_EQ("300,10 100x100",
272             fullscreen->GetWindowBoundsInScreen().ToString());
273   EXPECT_EQ("300,10 100x100",
274             fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString());
275
276   // Test if the unparented widget has moved.
277   EXPECT_EQ(root_windows[0],
278             unparented_control->GetNativeView()->GetRootWindow());
279   EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer,
280             unparented_control->GetNativeView()->parent()->id());
281
282   // Test if the panel has moved.
283   EXPECT_EQ(root_windows[0], panel->GetRootWindow());
284   EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id());
285 }
286
287 TEST_F(RootWindowControllerTest, MoveWindows_Modal) {
288   if (!SupportsMultipleDisplays())
289     return;
290
291   UpdateDisplay("500x500,500x500");
292
293   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
294   // Emulate virtual screen coordinate system.
295   root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500));
296   root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500));
297
298   views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100));
299   EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow());
300   EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView()));
301
302   views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100));
303   EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow());
304   EXPECT_TRUE(GetModalContainer(root_windows[1])->Contains(
305       modal->GetNativeView()));
306   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
307
308   aura::test::EventGenerator generator_1st(root_windows[0]);
309   generator_1st.ClickLeftButton();
310   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
311
312   UpdateDisplay("500x500");
313   EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow());
314   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
315   generator_1st.ClickLeftButton();
316   EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView()));
317 }
318
319 TEST_F(RootWindowControllerTest, ModalContainer) {
320   UpdateDisplay("600x600");
321   Shell* shell = Shell::GetInstance();
322   internal::RootWindowController* controller =
323       shell->GetPrimaryRootWindowController();
324   EXPECT_EQ(user::LOGGED_IN_USER,
325             shell->system_tray_delegate()->GetUserLoginStatus());
326   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
327       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
328           controller->GetSystemModalLayoutManager(NULL));
329
330   views::Widget* session_modal_widget =
331       CreateModalWidget(gfx::Rect(300, 10, 100, 100));
332   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
333       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
334           controller->GetSystemModalLayoutManager(
335               session_modal_widget->GetNativeView()));
336
337   shell->session_state_delegate()->LockScreen();
338   EXPECT_EQ(user::LOGGED_IN_LOCKED,
339             shell->system_tray_delegate()->GetUserLoginStatus());
340   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
341       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
342           controller->GetSystemModalLayoutManager(NULL));
343
344   aura::Window* lock_container =
345       Shell::GetContainer(controller->root_window(),
346                           internal::kShellWindowId_LockScreenContainer);
347   views::Widget* lock_modal_widget =
348       CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
349   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
350       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
351           controller->GetSystemModalLayoutManager(
352               lock_modal_widget->GetNativeView()));
353   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
354         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
355             controller->GetSystemModalLayoutManager(
356                 session_modal_widget->GetNativeView()));
357
358   shell->session_state_delegate()->UnlockScreen();
359 }
360
361 TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
362   UpdateDisplay("600x600");
363   Shell* shell = Shell::GetInstance();
364
365   // Configure login screen environment.
366   SetUserLoggedIn(false);
367   EXPECT_EQ(user::LOGGED_IN_NONE,
368             shell->system_tray_delegate()->GetUserLoginStatus());
369   EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers());
370   EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted());
371
372   internal::RootWindowController* controller =
373       shell->GetPrimaryRootWindowController();
374   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
375       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
376           controller->GetSystemModalLayoutManager(NULL));
377
378   aura::Window* lock_container =
379       Shell::GetContainer(controller->root_window(),
380                           internal::kShellWindowId_LockScreenContainer);
381   views::Widget* login_modal_widget =
382       CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container);
383   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
384       internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
385           controller->GetSystemModalLayoutManager(
386               login_modal_widget->GetNativeView()));
387   login_modal_widget->Close();
388
389   // Configure user session environment.
390   SetUserLoggedIn(true);
391   SetSessionStarted(true);
392   EXPECT_EQ(user::LOGGED_IN_USER,
393             shell->system_tray_delegate()->GetUserLoginStatus());
394   EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers());
395   EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted());
396   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
397       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
398           controller->GetSystemModalLayoutManager(NULL));
399
400   views::Widget* session_modal_widget =
401         CreateModalWidget(gfx::Rect(300, 10, 100, 100));
402   EXPECT_EQ(Shell::GetContainer(controller->root_window(),
403       internal::kShellWindowId_SystemModalContainer)->layout_manager(),
404           controller->GetSystemModalLayoutManager(
405               session_modal_widget->GetNativeView()));
406 }
407
408 TEST_F(RootWindowControllerTest, ModalContainerBlockedSession) {
409   UpdateDisplay("600x600");
410   Shell* shell = Shell::GetInstance();
411   internal::RootWindowController* controller =
412       shell->GetPrimaryRootWindowController();
413   aura::Window* lock_container =
414       Shell::GetContainer(controller->root_window(),
415                           internal::kShellWindowId_LockScreenContainer);
416   for (int block_reason = FIRST_BLOCK_REASON;
417        block_reason < NUMBER_OF_BLOCK_REASONS;
418        ++block_reason) {
419     views::Widget* session_modal_widget =
420           CreateModalWidget(gfx::Rect(300, 10, 100, 100));
421     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
422         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
423             controller->GetSystemModalLayoutManager(
424                 session_modal_widget->GetNativeView()));
425     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
426         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
427             controller->GetSystemModalLayoutManager(NULL));
428     session_modal_widget->Close();
429
430     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
431
432     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
433         internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
434             controller->GetSystemModalLayoutManager(NULL));
435
436     views::Widget* lock_modal_widget =
437         CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100),
438                                     lock_container);
439     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
440         internal::kShellWindowId_LockSystemModalContainer)->layout_manager(),
441               controller->GetSystemModalLayoutManager(
442                   lock_modal_widget->GetNativeView()));
443
444     session_modal_widget =
445           CreateModalWidget(gfx::Rect(300, 10, 100, 100));
446     EXPECT_EQ(Shell::GetContainer(controller->root_window(),
447         internal::kShellWindowId_SystemModalContainer)->layout_manager(),
448             controller->GetSystemModalLayoutManager(
449                 session_modal_widget->GetNativeView()));
450     session_modal_widget->Close();
451
452     lock_modal_widget->Close();
453     UnblockUserSession();
454   }
455 }
456
457 TEST_F(RootWindowControllerTest, GetTopmostFullscreenWindow) {
458   UpdateDisplay("600x600");
459   internal::RootWindowController* controller =
460       Shell::GetInstance()->GetPrimaryRootWindowController();
461
462   Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
463   w1->Maximize();
464   Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
465   w2->SetFullscreen(true);
466   // |w3| is a transient child of |w2|.
467   Widget* w3 = Widget::CreateWindowWithParentAndBounds(NULL,
468       w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100));
469
470   // Test that GetTopmostFullscreenWindow() finds the fullscreen window when one
471   // of its transient children is active.
472   w3->Activate();
473   EXPECT_EQ(w2->GetNativeWindow(), controller->GetTopmostFullscreenWindow());
474
475   // Since there's only one desktop workspace, it always returns the same
476   // fullscreen window.
477   w1->Activate();
478   EXPECT_EQ(w2->GetNativeWindow(), controller->GetTopmostFullscreenWindow());
479 }
480
481 TEST_F(RootWindowControllerTest, MultipleFullscreenWindows) {
482   UpdateDisplay("600x600");
483   internal::RootWindowController* controller =
484       Shell::GetInstance()->GetPrimaryRootWindowController();
485
486   Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
487   w1->Maximize();
488   Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
489   w2->SetFullscreen(true);
490   Widget* w3 = CreateTestWidget(gfx::Rect(0, 0, 100, 100));
491   w3->SetFullscreen(true);
492
493   // Test that GetTopmostFullscreenWindow() finds the active fullscreen window.
494   w2->Activate();
495   EXPECT_EQ(w2->GetNativeWindow(), controller->GetTopmostFullscreenWindow());
496   w3->Activate();
497   EXPECT_EQ(w3->GetNativeWindow(), controller->GetTopmostFullscreenWindow());
498
499   // If the active window is not fullscreen, it still returns the topmost
500   // fullscreen window, which is the last active one.
501   w1->Activate();
502   EXPECT_EQ(w3->GetNativeWindow(), controller->GetTopmostFullscreenWindow());
503 }
504
505 // Test that user session window can't be focused if user session blocked by
506 // some overlapping UI.
507 TEST_F(RootWindowControllerTest, FocusBlockedWindow) {
508   UpdateDisplay("600x600");
509   internal::RootWindowController* controller =
510       Shell::GetInstance()->GetPrimaryRootWindowController();
511   aura::Window* lock_container =
512       Shell::GetContainer(controller->root_window(),
513                           internal::kShellWindowId_LockScreenContainer);
514   aura::Window* lock_window = Widget::CreateWindowWithParentAndBounds(NULL,
515       lock_container, gfx::Rect(0, 0, 100, 100))->GetNativeView();
516   lock_window->Show();
517   aura::Window* session_window =
518       CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView();
519   session_window->Show();
520
521   for (int block_reason = FIRST_BLOCK_REASON;
522        block_reason < NUMBER_OF_BLOCK_REASONS;
523        ++block_reason) {
524     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
525     lock_window->Focus();
526     EXPECT_TRUE(lock_window->HasFocus());
527     session_window->Focus();
528     EXPECT_FALSE(session_window->HasFocus());
529     UnblockUserSession();
530   }
531 }
532
533 // Tracks whether OnWindowDestroying() has been invoked.
534 class DestroyedWindowObserver : public aura::WindowObserver {
535  public:
536   DestroyedWindowObserver() : destroyed_(false), window_(NULL) {}
537   virtual ~DestroyedWindowObserver() {
538     Shutdown();
539   }
540
541   void SetWindow(Window* window) {
542     window_ = window;
543     window->AddObserver(this);
544   }
545
546   bool destroyed() const { return destroyed_; }
547
548   // WindowObserver overrides:
549   virtual void OnWindowDestroying(Window* window) OVERRIDE {
550     destroyed_ = true;
551     Shutdown();
552   }
553
554  private:
555   void Shutdown() {
556     if (!window_)
557       return;
558     window_->RemoveObserver(this);
559     window_ = NULL;
560   }
561
562   bool destroyed_;
563   Window* window_;
564
565   DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver);
566 };
567
568 // Verifies shutdown doesn't delete windows that are not owned by the parent.
569 TEST_F(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) {
570   DestroyedWindowObserver observer1;
571   aura::test::TestWindowDelegate delegate1;
572   aura::Window* window1 = new aura::Window(&delegate1);
573   window1->SetType(aura::client::WINDOW_TYPE_CONTROL);
574   window1->set_owned_by_parent(false);
575   observer1.SetWindow(window1);
576   window1->Init(ui::LAYER_NOT_DRAWN);
577   aura::client::ParentWindowWithContext(
578       window1, Shell::GetInstance()->GetPrimaryRootWindow(), gfx::Rect());
579
580   DestroyedWindowObserver observer2;
581   aura::Window* window2 = new aura::Window(NULL);
582   window2->set_owned_by_parent(false);
583   observer2.SetWindow(window2);
584   window2->Init(ui::LAYER_NOT_DRAWN);
585   Shell::GetInstance()->GetPrimaryRootWindow()->AddChild(window2);
586
587   Shell::GetInstance()->GetPrimaryRootWindowController()->CloseChildWindows();
588
589   ASSERT_FALSE(observer1.destroyed());
590   delete window1;
591
592   ASSERT_FALSE(observer2.destroyed());
593   delete window2;
594 }
595
596 typedef test::NoSessionAshTestBase NoSessionRootWindowControllerTest;
597
598 // Make sure that an event handler exists for entire display area.
599 TEST_F(NoSessionRootWindowControllerTest, Event) {
600   aura::Window* root = Shell::GetPrimaryRootWindow();
601   const gfx::Size size = root->bounds().size();
602   aura::Window* event_target = root->GetEventHandlerForPoint(gfx::Point(0, 0));
603   EXPECT_TRUE(event_target);
604   EXPECT_EQ(event_target,
605             root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
606   EXPECT_EQ(event_target,
607             root->GetEventHandlerForPoint(gfx::Point(size.width() - 1, 0)));
608   EXPECT_EQ(event_target,
609             root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1)));
610   EXPECT_EQ(event_target,
611             root->GetEventHandlerForPoint(
612                 gfx::Point(size.width() - 1, size.height() - 1)));
613 }
614
615 class VirtualKeyboardRootWindowControllerTest : public test::AshTestBase {
616  public:
617   VirtualKeyboardRootWindowControllerTest() {};
618   virtual ~VirtualKeyboardRootWindowControllerTest() {};
619
620   virtual void SetUp() OVERRIDE {
621     CommandLine::ForCurrentProcess()->AppendSwitch(
622         keyboard::switches::kEnableVirtualKeyboard);
623     test::AshTestBase::SetUp();
624     Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
625         Shell::GetInstance()->keyboard_controller());
626   }
627
628  private:
629   DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest);
630 };
631
632 // Test for http://crbug.com/297858. Virtual keyboard container should only show
633 // on primary root window.
634 TEST_F(VirtualKeyboardRootWindowControllerTest,
635        VirtualKeyboardOnPrimaryRootWindowOnly) {
636   if (!SupportsMultipleDisplays())
637     return;
638
639   UpdateDisplay("500x500,500x500");
640
641   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
642   aura::Window* primary_root_window = Shell::GetPrimaryRootWindow();
643   aura::Window* secondary_root_window =
644       root_windows[0] == primary_root_window ?
645           root_windows[1] : root_windows[0];
646
647   ASSERT_TRUE(Shell::GetContainer(
648       primary_root_window,
649       internal::kShellWindowId_VirtualKeyboardContainer));
650   ASSERT_FALSE(Shell::GetContainer(
651       secondary_root_window,
652       internal::kShellWindowId_VirtualKeyboardContainer));
653 }
654
655 // Test for http://crbug.com/263599. Virtual keyboard should be able to receive
656 // events at blocked user session.
657 TEST_F(VirtualKeyboardRootWindowControllerTest,
658        ClickVirtualKeyboardInBlockedWindow) {
659   aura::Window* root_window = Shell::GetPrimaryRootWindow();
660   aura::Window* keyboard_container = Shell::GetContainer(root_window,
661       internal::kShellWindowId_VirtualKeyboardContainer);
662   ASSERT_TRUE(keyboard_container);
663   keyboard_container->Show();
664
665   ClickTestWindow* main_delegate = new ClickTestWindow();
666   scoped_ptr<aura::Window> keyboard_window(
667       main_delegate->CreateTestWindowWithParent(keyboard_container));
668   keyboard_container->layout_manager()->OnWindowResized();
669   keyboard_window->Show();
670   aura::test::EventGenerator event_generator(root_window,
671                                              keyboard_window.get());
672   event_generator.ClickLeftButton();
673   int expected_mouse_presses = 1;
674   EXPECT_EQ(expected_mouse_presses, main_delegate->mouse_presses());
675
676   for (int block_reason = FIRST_BLOCK_REASON;
677        block_reason < NUMBER_OF_BLOCK_REASONS;
678        ++block_reason) {
679     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
680     event_generator.ClickLeftButton();
681     expected_mouse_presses++;
682     EXPECT_EQ(expected_mouse_presses, main_delegate->mouse_presses());
683     UnblockUserSession();
684   }
685 }
686
687 // Test for http://crbug.com/299787. RootWindowController should delete
688 // the old container since the keyboard controller creates a new window in
689 // GetWindowContainer().
690 TEST_F(VirtualKeyboardRootWindowControllerTest,
691        DeleteOldContainerOnVirtualKeyboardInit) {
692   aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
693   aura::Window* keyboard_container = Shell::GetContainer(root_window,
694       internal::kShellWindowId_VirtualKeyboardContainer);
695   ASSERT_TRUE(keyboard_container);
696   // Track the keyboard container window.
697   aura::WindowTracker tracker;
698   tracker.Add(keyboard_container);
699   // Mock a login state change to reinitialize the keyboard.
700   ash::Shell::GetInstance()->OnLoginStateChanged(user::LOGGED_IN_OWNER);
701   // keyboard_container should no longer be present.
702   EXPECT_FALSE(tracker.Contains(keyboard_container));
703 }
704
705 }  // namespace test
706 }  // namespace ash