Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / ash / wm / workspace_controller_unittest.cc
1 // Copyright 2013 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/workspace_controller.h"
6
7 #include <map>
8
9 #include "ash/ash_switches.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/screen_util.h"
12 #include "ash/shelf/shelf_layout_manager.h"
13 #include "ash/shelf/shelf_widget.h"
14 #include "ash/shell.h"
15 #include "ash/shell_window_ids.h"
16 #include "ash/system/status_area_widget.h"
17 #include "ash/test/ash_test_base.h"
18 #include "ash/test/shell_test_api.h"
19 #include "ash/test/test_shelf_delegate.h"
20 #include "ash/wm/panels/panel_layout_manager.h"
21 #include "ash/wm/window_state.h"
22 #include "ash/wm/window_util.h"
23 #include "ash/wm/workspace/workspace_window_resizer.h"
24 #include "base/command_line.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "ui/aura/client/aura_constants.h"
27 #include "ui/aura/test/event_generator.h"
28 #include "ui/aura/test/test_window_delegate.h"
29 #include "ui/aura/test/test_windows.h"
30 #include "ui/aura/window.h"
31 #include "ui/aura/window_event_dispatcher.h"
32 #include "ui/base/hit_test.h"
33 #include "ui/base/ui_base_types.h"
34 #include "ui/compositor/layer.h"
35 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
36 #include "ui/events/event_utils.h"
37 #include "ui/gfx/screen.h"
38 #include "ui/views/widget/widget.h"
39 #include "ui/wm/core/window_animations.h"
40 #include "ui/wm/core/window_util.h"
41
42 using aura::Window;
43
44 namespace ash {
45 namespace internal {
46
47 // Returns a string containing the names of all the children of |window| (in
48 // order). Each entry is separated by a space.
49 std::string GetWindowNames(const aura::Window* window) {
50   std::string result;
51   for (size_t i = 0; i < window->children().size(); ++i) {
52     if (i != 0)
53       result += " ";
54     result += window->children()[i]->name();
55   }
56   return result;
57 }
58
59 // Returns a string containing the names of windows corresponding to each of the
60 // child layers of |window|'s layer. Any layers that don't correspond to a child
61 // Window of |window| are ignored. The result is ordered based on the layer
62 // ordering.
63 std::string GetLayerNames(const aura::Window* window) {
64   typedef std::map<const ui::Layer*, std::string> LayerToWindowNameMap;
65   LayerToWindowNameMap window_names;
66   for (size_t i = 0; i < window->children().size(); ++i) {
67     window_names[window->children()[i]->layer()] =
68         window->children()[i]->name();
69   }
70
71   std::string result;
72   const std::vector<ui::Layer*>& layers(window->layer()->children());
73   for (size_t i = 0; i < layers.size(); ++i) {
74     LayerToWindowNameMap::iterator layer_i =
75         window_names.find(layers[i]);
76     if (layer_i != window_names.end()) {
77       if (!result.empty())
78         result += " ";
79       result += layer_i->second;
80     }
81   }
82   return result;
83 }
84
85 class WorkspaceControllerTest : public test::AshTestBase {
86  public:
87   WorkspaceControllerTest() {}
88   virtual ~WorkspaceControllerTest() {}
89
90   aura::Window* CreateTestWindowUnparented() {
91     aura::Window* window = new aura::Window(NULL);
92     window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
93     window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
94     window->Init(aura::WINDOW_LAYER_TEXTURED);
95     return window;
96   }
97
98   aura::Window* CreateTestWindow() {
99     aura::Window* window = new aura::Window(NULL);
100     window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
101     window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
102     window->Init(aura::WINDOW_LAYER_TEXTURED);
103     ParentWindowInPrimaryRootWindow(window);
104     return window;
105   }
106
107   aura::Window* CreateBrowserLikeWindow(const gfx::Rect& bounds) {
108     aura::Window* window = CreateTestWindow();
109     window->SetBounds(bounds);
110     wm::WindowState* window_state = wm::GetWindowState(window);
111     window_state->set_window_position_managed(true);
112     window->Show();
113     return window;
114   }
115
116   aura::Window* CreatePopupLikeWindow(const gfx::Rect& bounds) {
117     aura::Window* window = CreateTestWindowInShellWithBounds(bounds);
118     window->Show();
119     return window;
120   }
121
122   aura::Window* CreateTestPanel(aura::WindowDelegate* delegate,
123                                 const gfx::Rect& bounds) {
124     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
125         delegate,
126         ui::wm::WINDOW_TYPE_PANEL,
127         0,
128         bounds);
129     test::TestShelfDelegate* shelf_delegate =
130         test::TestShelfDelegate::instance();
131     shelf_delegate->AddShelfItem(window);
132     PanelLayoutManager* manager =
133         static_cast<PanelLayoutManager*>(
134             Shell::GetContainer(window->GetRootWindow(),
135                                 internal::kShellWindowId_PanelContainer)->
136                                 layout_manager());
137     manager->Relayout();
138     return window;
139   }
140
141   aura::Window* GetDesktop() {
142     return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
143                                kShellWindowId_DefaultContainer);
144   }
145
146   gfx::Rect GetFullscreenBounds(aura::Window* window) {
147     return Shell::GetScreen()->GetDisplayNearestWindow(window).bounds();
148   }
149
150   ShelfWidget* shelf_widget() {
151     return Shell::GetPrimaryRootWindowController()->shelf();
152   }
153
154   ShelfLayoutManager* shelf_layout_manager() {
155     return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
156   }
157
158   bool GetWindowOverlapsShelf() {
159     return shelf_layout_manager()->window_overlaps_shelf();
160   }
161
162  private:
163   DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTest);
164 };
165
166 // Assertions around adding a normal window.
167 TEST_F(WorkspaceControllerTest, AddNormalWindowWhenEmpty) {
168   scoped_ptr<Window> w1(CreateTestWindow());
169   w1->SetBounds(gfx::Rect(0, 0, 250, 251));
170
171   wm::WindowState* window_state = wm::GetWindowState(w1.get());
172
173   EXPECT_FALSE(window_state->HasRestoreBounds());
174
175   w1->Show();
176
177   EXPECT_FALSE(window_state->HasRestoreBounds());
178
179   ASSERT_TRUE(w1->layer() != NULL);
180   EXPECT_TRUE(w1->layer()->visible());
181
182   EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
183
184   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
185 }
186
187 // Assertions around maximizing/unmaximizing.
188 TEST_F(WorkspaceControllerTest, SingleMaximizeWindow) {
189   scoped_ptr<Window> w1(CreateTestWindow());
190   w1->SetBounds(gfx::Rect(0, 0, 250, 251));
191
192   w1->Show();
193   wm::ActivateWindow(w1.get());
194
195   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
196
197   ASSERT_TRUE(w1->layer() != NULL);
198   EXPECT_TRUE(w1->layer()->visible());
199
200   EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
201
202   // Maximize the window.
203   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
204
205   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
206
207   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
208   EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()).width(),
209             w1->bounds().width());
210   EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()).height(),
211             w1->bounds().height());
212
213   // Restore the window.
214   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
215
216   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
217   EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
218 }
219
220 // Assertions around two windows and toggling one to be fullscreen.
221 TEST_F(WorkspaceControllerTest, FullscreenWithNormalWindow) {
222   scoped_ptr<Window> w1(CreateTestWindow());
223   scoped_ptr<Window> w2(CreateTestWindow());
224   w1->SetBounds(gfx::Rect(0, 0, 250, 251));
225   w1->Show();
226
227   ASSERT_TRUE(w1->layer() != NULL);
228   EXPECT_TRUE(w1->layer()->visible());
229
230   w2->SetBounds(gfx::Rect(0, 0, 50, 51));
231   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
232   w2->Show();
233   wm::ActivateWindow(w2.get());
234
235   // Both windows should be in the same workspace.
236   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
237   EXPECT_EQ(w2.get(), GetDesktop()->children()[1]);
238
239   gfx::Rect work_area(
240       ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()));
241   EXPECT_EQ(work_area.width(), w2->bounds().width());
242   EXPECT_EQ(work_area.height(), w2->bounds().height());
243
244   // Restore w2, which should then go back to one workspace.
245   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
246   EXPECT_EQ(50, w2->bounds().width());
247   EXPECT_EQ(51, w2->bounds().height());
248   EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
249 }
250
251 // Makes sure requests to change the bounds of a normal window go through.
252 TEST_F(WorkspaceControllerTest, ChangeBoundsOfNormalWindow) {
253   scoped_ptr<Window> w1(CreateTestWindow());
254   w1->Show();
255
256   // Setting the bounds should go through since the window is in the normal
257   // workspace.
258   w1->SetBounds(gfx::Rect(0, 0, 200, 500));
259   EXPECT_EQ(200, w1->bounds().width());
260   EXPECT_EQ(500, w1->bounds().height());
261 }
262
263 // Verifies the bounds is not altered when showing and grid is enabled.
264 TEST_F(WorkspaceControllerTest, SnapToGrid) {
265   scoped_ptr<Window> w1(CreateTestWindowUnparented());
266   w1->SetBounds(gfx::Rect(1, 6, 25, 30));
267   ParentWindowInPrimaryRootWindow(w1.get());
268   // We are not aligning this anymore this way. When the window gets shown
269   // the window is expected to be handled differently, but this cannot be
270   // tested with this test. So the result of this test should be that the
271   // bounds are exactly as passed in.
272   EXPECT_EQ("1,6 25x30", w1->bounds().ToString());
273 }
274
275 // Assertions around a fullscreen window.
276 TEST_F(WorkspaceControllerTest, SingleFullscreenWindow) {
277   scoped_ptr<Window> w1(CreateTestWindow());
278   w1->SetBounds(gfx::Rect(0, 0, 250, 251));
279   // Make the window fullscreen.
280   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
281   w1->Show();
282   wm::ActivateWindow(w1.get());
283
284   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
285   EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width());
286   EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height());
287
288   // Restore the window. Use SHOW_STATE_DEFAULT as that is what we'll end up
289   // with when using views::Widget.
290   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_DEFAULT);
291   EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
292
293   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
294   EXPECT_EQ(250, w1->bounds().width());
295   EXPECT_EQ(251, w1->bounds().height());
296
297   // Back to fullscreen.
298   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
299   EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
300   EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width());
301   EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height());
302   wm::WindowState* window_state = wm::GetWindowState(w1.get());
303
304   ASSERT_TRUE(window_state->HasRestoreBounds());
305   EXPECT_EQ("0,0 250x251", window_state->GetRestoreBoundsInScreen().ToString());
306 }
307
308 // Assertions around minimizing a single window.
309 TEST_F(WorkspaceControllerTest, MinimizeSingleWindow) {
310   scoped_ptr<Window> w1(CreateTestWindow());
311
312   w1->Show();
313
314   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
315   EXPECT_FALSE(w1->layer()->IsDrawn());
316   EXPECT_TRUE(w1->layer()->GetTargetTransform().IsIdentity());
317
318   // Show the window.
319   w1->Show();
320   EXPECT_TRUE(wm::GetWindowState(w1.get())->IsNormalStateType());
321   EXPECT_TRUE(w1->layer()->IsDrawn());
322 }
323
324 // Assertions around minimizing a fullscreen window.
325 TEST_F(WorkspaceControllerTest, MinimizeFullscreenWindow) {
326   // Two windows, w1 normal, w2 fullscreen.
327   scoped_ptr<Window> w1(CreateTestWindow());
328   scoped_ptr<Window> w2(CreateTestWindow());
329   w1->Show();
330   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
331   w2->Show();
332
333   wm::WindowState* w1_state = wm::GetWindowState(w1.get());
334   wm::WindowState* w2_state = wm::GetWindowState(w2.get());
335
336   w2_state->Activate();
337
338   // Minimize w2.
339   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
340   EXPECT_TRUE(w1->layer()->IsDrawn());
341   EXPECT_FALSE(w2->layer()->IsDrawn());
342
343   // Show the window, which should trigger unminimizing.
344   w2->Show();
345   w2_state->Activate();
346
347   EXPECT_TRUE(w2_state->IsFullscreen());
348   EXPECT_TRUE(w1->layer()->IsDrawn());
349   EXPECT_TRUE(w2->layer()->IsDrawn());
350
351   // Minimize the window, which should hide the window.
352   EXPECT_TRUE(w2_state->IsActive());
353   w2_state->Minimize();
354   EXPECT_FALSE(w2_state->IsActive());
355   EXPECT_FALSE(w2->layer()->IsDrawn());
356   EXPECT_TRUE(w1_state->IsActive());
357   EXPECT_EQ(w2.get(), GetDesktop()->children()[0]);
358   EXPECT_EQ(w1.get(), GetDesktop()->children()[1]);
359
360   // Make the window normal.
361   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
362   // Setting back to normal doesn't change the activation.
363   EXPECT_FALSE(w2_state->IsActive());
364   EXPECT_TRUE(w1_state->IsActive());
365   EXPECT_EQ(w2.get(), GetDesktop()->children()[0]);
366   EXPECT_EQ(w1.get(), GetDesktop()->children()[1]);
367   EXPECT_TRUE(w2->layer()->IsDrawn());
368 }
369
370 // Verifies ShelfLayoutManager's visibility/auto-hide state is correctly
371 // updated.
372 TEST_F(WorkspaceControllerTest, ShelfStateUpdated) {
373   // Since ShelfLayoutManager queries for mouse location, move the mouse so
374   // it isn't over the shelf.
375   aura::test::EventGenerator generator(
376       Shell::GetPrimaryRootWindow(), gfx::Point());
377   generator.MoveMouseTo(0, 0);
378
379   scoped_ptr<Window> w1(CreateTestWindow());
380   const gfx::Rect w1_bounds(0, 1, 101, 102);
381   ShelfLayoutManager* shelf = shelf_layout_manager();
382   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
383   const gfx::Rect touches_shelf_bounds(
384       0, shelf->GetIdealBounds().y() - 10, 101, 102);
385   // Move |w1| to overlap the shelf.
386   w1->SetBounds(touches_shelf_bounds);
387   EXPECT_FALSE(GetWindowOverlapsShelf());
388
389   // A visible ignored window should not trigger the overlap.
390   scoped_ptr<Window> w_ignored(CreateTestWindow());
391   w_ignored->SetBounds(touches_shelf_bounds);
392   wm::GetWindowState(&(*w_ignored))->set_ignored_by_shelf(true);
393   w_ignored->Show();
394   EXPECT_FALSE(GetWindowOverlapsShelf());
395
396   // Make it visible, since visible shelf overlaps should be true.
397   w1->Show();
398   EXPECT_TRUE(GetWindowOverlapsShelf());
399
400   wm::ActivateWindow(w1.get());
401   w1->SetBounds(w1_bounds);
402   w1->Show();
403   wm::ActivateWindow(w1.get());
404
405   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
406
407   // Maximize the window.
408   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
409   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
410   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
411
412   // Restore.
413   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
414   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
415   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
416
417   // Fullscreen.
418   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
419   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
420
421   // Normal.
422   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
423   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
424   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
425   EXPECT_FALSE(GetWindowOverlapsShelf());
426
427   // Move window so it obscures shelf.
428   w1->SetBounds(touches_shelf_bounds);
429   EXPECT_TRUE(GetWindowOverlapsShelf());
430
431   // Move it back.
432   w1->SetBounds(w1_bounds);
433   EXPECT_FALSE(GetWindowOverlapsShelf());
434
435   // Maximize again.
436   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
437   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
438   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
439
440   // Minimize.
441   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
442   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
443
444   // Since the restore from minimize will restore to the pre-minimize
445   // state (tested elsewhere), we abandon the current size and restore
446   // rect and set them to the window.
447   wm::WindowState* window_state = wm::GetWindowState(w1.get());
448
449   gfx::Rect restore = window_state->GetRestoreBoundsInScreen();
450   EXPECT_EQ("0,0 800x597", w1->bounds().ToString());
451   EXPECT_EQ("0,1 101x102", restore.ToString());
452   window_state->ClearRestoreBounds();
453   w1->SetBounds(restore);
454
455   // Restore.
456   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
457   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
458   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
459
460   // Create another window, maximized.
461   scoped_ptr<Window> w2(CreateTestWindow());
462   w2->SetBounds(gfx::Rect(10, 11, 250, 251));
463   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
464   w2->Show();
465   wm::ActivateWindow(w2.get());
466   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
467   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
468   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
469   EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(
470                 w2->parent()).ToString(),
471             w2->bounds().ToString());
472
473   // Switch to w1.
474   wm::ActivateWindow(w1.get());
475   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
476   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
477   EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(
478                 w2->parent()).ToString(),
479             w2->bounds().ToString());
480
481   // Switch to w2.
482   wm::ActivateWindow(w2.get());
483   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
484   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
485   EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
486   EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w2.get()).ToString(),
487             w2->bounds().ToString());
488
489   // Turn off auto-hide, switch back to w2 (maximized) and verify overlap.
490   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
491   wm::ActivateWindow(w2.get());
492   EXPECT_FALSE(GetWindowOverlapsShelf());
493
494   // Move w1 to overlap shelf, it shouldn't change window overlaps shelf since
495   // the window isn't in the visible workspace.
496   w1->SetBounds(touches_shelf_bounds);
497   EXPECT_FALSE(GetWindowOverlapsShelf());
498
499   // Activate w1. Although w1 is visible, the overlap state is still false since
500   // w2 is maximized.
501   wm::ActivateWindow(w1.get());
502   EXPECT_FALSE(GetWindowOverlapsShelf());
503
504   // Restore w2.
505   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
506   EXPECT_TRUE(GetWindowOverlapsShelf());
507 }
508
509 // Verifies going from maximized to minimized sets the right state for painting
510 // the background of the launcher.
511 TEST_F(WorkspaceControllerTest, MinimizeResetsVisibility) {
512   scoped_ptr<Window> w1(CreateTestWindow());
513   w1->Show();
514   wm::ActivateWindow(w1.get());
515   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
516   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, shelf_widget()->GetBackgroundType());
517
518   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
519   EXPECT_EQ(SHELF_VISIBLE,
520             shelf_layout_manager()->visibility_state());
521   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, shelf_widget()->GetBackgroundType());
522 }
523
524 // Verifies window visibility during various workspace changes.
525 TEST_F(WorkspaceControllerTest, VisibilityTests) {
526   scoped_ptr<Window> w1(CreateTestWindow());
527   w1->Show();
528   EXPECT_TRUE(w1->IsVisible());
529   EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
530
531   // Create another window, activate it and make it fullscreen.
532   scoped_ptr<Window> w2(CreateTestWindow());
533   w2->Show();
534   wm::ActivateWindow(w2.get());
535   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
536   EXPECT_TRUE(w2->IsVisible());
537   EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
538   EXPECT_TRUE(w1->IsVisible());
539
540   // Switch to w1. |w1| should be visible on top of |w2|.
541   wm::ActivateWindow(w1.get());
542   EXPECT_TRUE(w1->IsVisible());
543   EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
544   EXPECT_TRUE(w2->IsVisible());
545
546   // Switch back to |w2|.
547   wm::ActivateWindow(w2.get());
548   EXPECT_TRUE(w2->IsVisible());
549   EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
550   EXPECT_TRUE(w1->IsVisible());
551
552   // Restore |w2|, both windows should be visible.
553   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
554   EXPECT_TRUE(w1->IsVisible());
555   EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
556   EXPECT_TRUE(w2->IsVisible());
557   EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
558
559   // Make |w2| fullscreen again, then close it.
560   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
561   w2->Hide();
562   EXPECT_FALSE(w2->IsVisible());
563   EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
564   EXPECT_TRUE(w1->IsVisible());
565
566   // Create |w2| and maximize it.
567   w2.reset(CreateTestWindow());
568   w2->Show();
569   wm::ActivateWindow(w2.get());
570   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
571   EXPECT_TRUE(w2->IsVisible());
572   EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
573   EXPECT_TRUE(w1->IsVisible());
574
575   // Close |w2|.
576   w2.reset();
577   EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
578   EXPECT_TRUE(w1->IsVisible());
579 }
580
581 // Verifies windows that are offscreen don't move when switching workspaces.
582 TEST_F(WorkspaceControllerTest, DontMoveOnSwitch) {
583   aura::test::EventGenerator generator(
584       Shell::GetPrimaryRootWindow(), gfx::Point());
585   generator.MoveMouseTo(0, 0);
586
587   scoped_ptr<Window> w1(CreateTestWindow());
588   ShelfLayoutManager* shelf = shelf_layout_manager();
589   const gfx::Rect touches_shelf_bounds(
590       0, shelf->GetIdealBounds().y() - 10, 101, 102);
591   // Move |w1| to overlap the shelf.
592   w1->SetBounds(touches_shelf_bounds);
593   w1->Show();
594   wm::ActivateWindow(w1.get());
595
596   // Create another window and maximize it.
597   scoped_ptr<Window> w2(CreateTestWindow());
598   w2->SetBounds(gfx::Rect(10, 11, 250, 251));
599   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
600   w2->Show();
601   wm::ActivateWindow(w2.get());
602
603   // Switch to w1.
604   wm::ActivateWindow(w1.get());
605   EXPECT_EQ(touches_shelf_bounds.ToString(), w1->bounds().ToString());
606 }
607
608 // Verifies that windows that are completely offscreen move when switching
609 // workspaces.
610 TEST_F(WorkspaceControllerTest, MoveOnSwitch) {
611   aura::test::EventGenerator generator(
612       Shell::GetPrimaryRootWindow(), gfx::Point());
613   generator.MoveMouseTo(0, 0);
614
615   scoped_ptr<Window> w1(CreateTestWindow());
616   ShelfLayoutManager* shelf = shelf_layout_manager();
617   const gfx::Rect w1_bounds(0, shelf->GetIdealBounds().y(), 100, 200);
618   // Move |w1| so that the top edge is the same as the top edge of the shelf.
619   w1->SetBounds(w1_bounds);
620   w1->Show();
621   wm::ActivateWindow(w1.get());
622   EXPECT_EQ(w1_bounds.ToString(), w1->bounds().ToString());
623
624   // Create another window and maximize it.
625   scoped_ptr<Window> w2(CreateTestWindow());
626   w2->SetBounds(gfx::Rect(10, 11, 250, 251));
627   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
628   w2->Show();
629   wm::ActivateWindow(w2.get());
630
631   // Increase the size of the WorkAreaInsets. This would make |w1| fall
632   // completely out of the display work area.
633   gfx::Insets insets =
634       Shell::GetScreen()->GetPrimaryDisplay().GetWorkAreaInsets();
635   insets.Set(0, 0, insets.bottom() + 30, 0);
636   Shell::GetInstance()->SetDisplayWorkAreaInsets(w1.get(), insets);
637
638   // Switch to w1. The window should have moved.
639   wm::ActivateWindow(w1.get());
640   EXPECT_NE(w1_bounds.ToString(), w1->bounds().ToString());
641 }
642
643 namespace {
644
645 // WindowDelegate used by DontCrashOnChangeAndActivate.
646 class DontCrashOnChangeAndActivateDelegate
647     : public aura::test::TestWindowDelegate {
648  public:
649   DontCrashOnChangeAndActivateDelegate() : window_(NULL) {}
650
651   void set_window(aura::Window* window) { window_ = window; }
652
653   // WindowDelegate overrides:
654   virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
655                                const gfx::Rect& new_bounds) OVERRIDE {
656     if (window_) {
657       wm::ActivateWindow(window_);
658       window_ = NULL;
659     }
660   }
661
662  private:
663   aura::Window* window_;
664
665   DISALLOW_COPY_AND_ASSIGN(DontCrashOnChangeAndActivateDelegate);
666 };
667
668 }  // namespace
669
670 // Exercises possible crash in W2. Here's the sequence:
671 // . minimize a maximized window.
672 // . remove the window (which happens when switching displays).
673 // . add the window back.
674 // . show the window and during the bounds change activate it.
675 TEST_F(WorkspaceControllerTest, DontCrashOnChangeAndActivate) {
676   // Force the shelf
677   ShelfLayoutManager* shelf = shelf_layout_manager();
678   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
679
680   DontCrashOnChangeAndActivateDelegate delegate;
681   scoped_ptr<Window> w1(CreateTestWindowInShellWithDelegate(
682       &delegate, 1000, gfx::Rect(10, 11, 250, 251)));
683
684   w1->Show();
685   wm::WindowState* w1_state = wm::GetWindowState(w1.get());
686   w1_state->Activate();
687   w1_state->Maximize();
688   w1_state->Minimize();
689
690   w1->parent()->RemoveChild(w1.get());
691
692   // Do this so that when we Show() the window a resize occurs and we make the
693   // window active.
694   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
695
696   ParentWindowInPrimaryRootWindow(w1.get());
697   delegate.set_window(w1.get());
698   w1->Show();
699 }
700
701 // Verifies a window with a transient parent not managed by workspace works.
702 TEST_F(WorkspaceControllerTest, TransientParent) {
703   // Normal window with no transient parent.
704   scoped_ptr<Window> w2(CreateTestWindow());
705   w2->SetBounds(gfx::Rect(10, 11, 250, 251));
706   w2->Show();
707   wm::ActivateWindow(w2.get());
708
709   // Window with a transient parent. We set the transient parent to the root,
710   // which would never happen but is enough to exercise the bug.
711   scoped_ptr<Window> w1(CreateTestWindowUnparented());
712   ::wm::AddTransientChild(
713       Shell::GetInstance()->GetPrimaryRootWindow(), w1.get());
714   w1->SetBounds(gfx::Rect(10, 11, 250, 251));
715   ParentWindowInPrimaryRootWindow(w1.get());
716   w1->Show();
717   wm::ActivateWindow(w1.get());
718
719   // The window with the transient parent should get added to the same parent as
720   // the normal window.
721   EXPECT_EQ(w2->parent(), w1->parent());
722 }
723
724 // Test the placement of newly created windows.
725 TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnCreate) {
726   if (!SupportsHostWindowResize())
727     return;
728   UpdateDisplay("1600x1200");
729   // Creating a popup handler here to make sure it does not interfere with the
730   // existing windows.
731   gfx::Rect source_browser_bounds(16, 32, 640, 320);
732   scoped_ptr<aura::Window> browser_window(CreateBrowserLikeWindow(
733       source_browser_bounds));
734
735   // Creating a popup to make sure it does not interfere with the positioning.
736   scoped_ptr<aura::Window> browser_popup(CreatePopupLikeWindow(
737       gfx::Rect(16, 32, 128, 256)));
738
739   browser_window->Show();
740   browser_popup->Show();
741
742   { // With a shown window it's size should get returned.
743     scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
744         source_browser_bounds));
745     // The position should be right flush.
746     EXPECT_EQ("960,32 640x320", new_browser_window->bounds().ToString());
747   }
748
749   { // With the window shown - but more on the right side then on the left
750     // side (and partially out of the screen), it should default to the other
751     // side and inside the screen.
752     gfx::Rect source_browser_bounds(gfx::Rect(1000, 600, 640, 320));
753     browser_window->SetBounds(source_browser_bounds);
754
755     scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
756         source_browser_bounds));
757     // The position should be left & bottom flush.
758     EXPECT_EQ("0,600 640x320", new_browser_window->bounds().ToString());
759
760     // If the other window was already beyond the point to get right flush
761     // it will remain where it is.
762     EXPECT_EQ("1000,600 640x320", browser_window->bounds().ToString());
763   }
764
765   { // Make sure that popups do not get changed.
766     scoped_ptr<aura::Window> new_popup_window(CreatePopupLikeWindow(
767         gfx::Rect(50, 100, 300, 150)));
768     EXPECT_EQ("50,100 300x150", new_popup_window->bounds().ToString());
769   }
770
771   browser_window->Hide();
772   { // If a window is there but not shown the default should be centered.
773     scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
774         gfx::Rect(50, 100, 300, 150)));
775     EXPECT_EQ("650,100 300x150", new_browser_window->bounds().ToString());
776   }
777 }
778
779 // Test the basic auto placement of one and or two windows in a "simulated
780 // session" of sequential window operations.
781 TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnShowHide) {
782   // Test 1: In case there is no manageable window, no window should shift.
783
784   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
785   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
786   gfx::Rect desktop_area = window1->parent()->bounds();
787
788   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
789   // Trigger the auto window placement function by making it visible.
790   // Note that the bounds are getting changed while it is invisible.
791   window2->Hide();
792   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
793   window2->Show();
794
795   // Check the initial position of the windows is unchanged.
796   EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
797   EXPECT_EQ("32,48 256x512", window2->bounds().ToString());
798
799   // Remove the second window and make sure that the first window
800   // does NOT get centered.
801   window2.reset();
802   EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
803
804   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
805   // Test 2: Set up two managed windows and check their auto positioning.
806   window1_state->set_window_position_managed(true);
807
808   scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(2));
809   wm::GetWindowState(window3.get())->set_window_position_managed(true);
810   // To avoid any auto window manager changes due to SetBounds, the window
811   // gets first hidden and then shown again.
812   window3->Hide();
813   window3->SetBounds(gfx::Rect(32, 48, 256, 512));
814   window3->Show();
815   // |window1| should be flush left and |window3| flush right.
816   EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
817   EXPECT_EQ(base::IntToString(
818                 desktop_area.width() - window3->bounds().width()) +
819             ",48 256x512", window3->bounds().ToString());
820
821   // After removing |window3|, |window1| should be centered again.
822   window3.reset();
823   EXPECT_EQ(
824       base::IntToString(
825           (desktop_area.width() - window1->bounds().width()) / 2) +
826       ",32 640x320", window1->bounds().ToString());
827
828   // Test 3: Set up a manageable and a non manageable window and check
829   // positioning.
830   scoped_ptr<aura::Window> window4(CreateTestWindowInShellWithId(3));
831   // To avoid any auto window manager changes due to SetBounds, the window
832   // gets first hidden and then shown again.
833   window1->Hide();
834   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
835   window4->SetBounds(gfx::Rect(32, 48, 256, 512));
836   window1->Show();
837   // |window1| should be centered and |window4| untouched.
838   EXPECT_EQ(
839       base::IntToString(
840           (desktop_area.width() - window1->bounds().width()) / 2) +
841       ",32 640x320", window1->bounds().ToString());
842   EXPECT_EQ("32,48 256x512", window4->bounds().ToString());
843
844   // Test4: A single manageable window should get centered.
845   window4.reset();
846   window1_state->set_bounds_changed_by_user(false);
847   // Trigger the auto window placement function by showing (and hiding) it.
848   window1->Hide();
849   window1->Show();
850   // |window1| should be centered.
851   EXPECT_EQ(
852       base::IntToString(
853           (desktop_area.width() - window1->bounds().width()) / 2) +
854       ",32 640x320", window1->bounds().ToString());
855 }
856
857 // Test the proper usage of user window movement interaction.
858 TEST_F(WorkspaceControllerTest, TestUserMovedWindowRepositioning) {
859   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
860   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
861   gfx::Rect desktop_area = window1->parent()->bounds();
862   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
863   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
864   window1->Hide();
865   window2->Hide();
866   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
867   wm::WindowState* window2_state = wm::GetWindowState(window2.get());
868
869   window1_state->set_window_position_managed(true);
870   window2_state->set_window_position_managed(true);
871   EXPECT_FALSE(window1_state->bounds_changed_by_user());
872   EXPECT_FALSE(window2_state->bounds_changed_by_user());
873
874   // Check that the current location gets preserved if the user has
875   // positioned it previously.
876   window1_state->set_bounds_changed_by_user(true);
877   window1->Show();
878   EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
879   // Flag should be still set.
880   EXPECT_TRUE(window1_state->bounds_changed_by_user());
881   EXPECT_FALSE(window2_state->bounds_changed_by_user());
882
883   // Turn on the second window and make sure that both windows are now
884   // positionable again (user movement cleared).
885   window2->Show();
886
887   // |window1| should be flush left and |window2| flush right.
888   EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
889   EXPECT_EQ(
890       base::IntToString(desktop_area.width() - window2->bounds().width()) +
891       ",48 256x512", window2->bounds().ToString());
892   // FLag should now be reset.
893   EXPECT_FALSE(window1_state->bounds_changed_by_user());
894   EXPECT_FALSE(window2_state->bounds_changed_by_user());
895
896   // Going back to one shown window should keep the state.
897   window1_state->set_bounds_changed_by_user(true);
898   window2->Hide();
899   EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
900   EXPECT_TRUE(window1_state->bounds_changed_by_user());
901 }
902
903 // Test if the single window will be restored at original position.
904 TEST_F(WorkspaceControllerTest, TestSingleWindowsRestoredBounds) {
905   scoped_ptr<aura::Window> window1(
906       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
907   scoped_ptr<aura::Window> window2(
908       CreateTestWindowInShellWithBounds(gfx::Rect(110, 110, 100, 100)));
909   scoped_ptr<aura::Window> window3(
910       CreateTestWindowInShellWithBounds(gfx::Rect(120, 120, 100, 100)));
911   window1->Hide();
912   window2->Hide();
913   window3->Hide();
914   wm::GetWindowState(window1.get())->set_window_position_managed(true);
915   wm::GetWindowState(window2.get())->set_window_position_managed(true);
916   wm::GetWindowState(window3.get())->set_window_position_managed(true);
917
918   window1->Show();
919   wm::ActivateWindow(window1.get());
920   window2->Show();
921   wm::ActivateWindow(window2.get());
922   window3->Show();
923   wm::ActivateWindow(window3.get());
924   EXPECT_EQ(0, window1->bounds().x());
925   EXPECT_EQ(window2->GetRootWindow()->bounds().right(),
926             window2->bounds().right());
927   EXPECT_EQ(0, window3->bounds().x());
928
929   window1->Hide();
930   EXPECT_EQ(window2->GetRootWindow()->bounds().right(),
931             window2->bounds().right());
932   EXPECT_EQ(0, window3->bounds().x());
933
934   // Being a single window will retore the original location.
935   window3->Hide();
936   wm::ActivateWindow(window2.get());
937   EXPECT_EQ("110,110 100x100", window2->bounds().ToString());
938
939   // Showing the 3rd will push the 2nd window left.
940   window3->Show();
941   wm::ActivateWindow(window3.get());
942   EXPECT_EQ(0, window2->bounds().x());
943   EXPECT_EQ(window3->GetRootWindow()->bounds().right(),
944             window3->bounds().right());
945
946   // Being a single window will retore the original location.
947   window2->Hide();
948   EXPECT_EQ("120,120 100x100", window3->bounds().ToString());
949 }
950
951 // Test that user placed windows go back to their user placement after the user
952 // closes all other windows.
953 TEST_F(WorkspaceControllerTest, TestUserHandledWindowRestore) {
954   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
955   gfx::Rect user_pos = gfx::Rect(16, 42, 640, 320);
956   window1->SetBounds(user_pos);
957   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
958
959   window1_state->SetPreAutoManageWindowBounds(user_pos);
960   gfx::Rect desktop_area = window1->parent()->bounds();
961
962   // Create a second window to let the auto manager kick in.
963   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
964   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
965   window1->Hide();
966   window2->Hide();
967   wm::GetWindowState(window1.get())->set_window_position_managed(true);
968   wm::GetWindowState(window2.get())->set_window_position_managed(true);
969   window1->Show();
970   EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString());
971   window2->Show();
972
973   // |window1| should be flush left and |window2| flush right.
974   EXPECT_EQ("0," + base::IntToString(user_pos.y()) +
975             " 640x320", window1->bounds().ToString());
976   EXPECT_EQ(
977       base::IntToString(desktop_area.width() - window2->bounds().width()) +
978       ",48 256x512", window2->bounds().ToString());
979   window2->Hide();
980
981   // After the other window get hidden the window has to move back to the
982   // previous position and the bounds should still be set and unchanged.
983   EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString());
984   ASSERT_TRUE(window1_state->pre_auto_manage_window_bounds());
985   EXPECT_EQ(user_pos.ToString(),
986             window1_state->pre_auto_manage_window_bounds()->ToString());
987 }
988
989 // Solo window should be restored to the bounds where a user moved to.
990 TEST_F(WorkspaceControllerTest, TestRestoreToUserModifiedBounds) {
991   if (!SupportsHostWindowResize())
992     return;
993
994   UpdateDisplay("400x300");
995   gfx::Rect default_bounds(10, 0, 100, 100);
996   scoped_ptr<aura::Window> window1(
997       CreateTestWindowInShellWithBounds(default_bounds));
998   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
999   window1->Hide();
1000   window1_state->set_window_position_managed(true);
1001   window1->Show();
1002   // First window is centered.
1003   EXPECT_EQ("150,0 100x100", window1->bounds().ToString());
1004   scoped_ptr<aura::Window> window2(
1005       CreateTestWindowInShellWithBounds(default_bounds));
1006   wm::WindowState* window2_state = wm::GetWindowState(window2.get());
1007   window2->Hide();
1008   window2_state->set_window_position_managed(true);
1009   window2->Show();
1010
1011   // Auto positioning pushes windows to each sides.
1012   EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
1013   EXPECT_EQ("300,0 100x100", window2->bounds().ToString());
1014
1015   window2->Hide();
1016   // Restores to the center.
1017   EXPECT_EQ("150,0 100x100", window1->bounds().ToString());
1018
1019   // A user moved the window.
1020   scoped_ptr<WindowResizer> resizer(CreateWindowResizer(
1021       window1.get(),
1022       gfx::Point(),
1023       HTCAPTION,
1024       aura::client::WINDOW_MOVE_SOURCE_MOUSE).release());
1025   gfx::Point location = resizer->GetInitialLocation();
1026   location.Offset(-50, 0);
1027   resizer->Drag(location, 0);
1028   resizer->CompleteDrag();
1029
1030   window1_state->set_bounds_changed_by_user(true);
1031   window1->SetBounds(gfx::Rect(100, 0, 100, 100));
1032
1033   window2->Show();
1034   EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
1035   EXPECT_EQ("300,0 100x100", window2->bounds().ToString());
1036
1037   // Window 1 should be restored to the user modified bounds.
1038   window2->Hide();
1039   EXPECT_EQ("100,0 100x100", window1->bounds().ToString());
1040 }
1041
1042 // Test that a window from normal to minimize will repos the remaining.
1043 TEST_F(WorkspaceControllerTest, ToMinimizeRepositionsRemaining) {
1044   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
1045   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
1046   window1_state->set_window_position_managed(true);
1047   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
1048   gfx::Rect desktop_area = window1->parent()->bounds();
1049
1050   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
1051   wm::WindowState* window2_state = wm::GetWindowState(window2.get());
1052   window2_state->set_window_position_managed(true);
1053   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
1054
1055   window1_state->Minimize();
1056
1057   // |window2| should be centered now.
1058   EXPECT_TRUE(window2->IsVisible());
1059   EXPECT_TRUE(window2_state->IsNormalStateType());
1060   EXPECT_EQ(base::IntToString(
1061                 (desktop_area.width() - window2->bounds().width()) / 2) +
1062             ",48 256x512", window2->bounds().ToString());
1063
1064   window1_state->Restore();
1065   // |window1| should be flush right and |window3| flush left.
1066   EXPECT_EQ(base::IntToString(
1067                 desktop_area.width() - window1->bounds().width()) +
1068             ",32 640x320", window1->bounds().ToString());
1069   EXPECT_EQ("0,48 256x512", window2->bounds().ToString());
1070 }
1071
1072 // Test that minimizing an initially maximized window will repos the remaining.
1073 TEST_F(WorkspaceControllerTest, MaxToMinRepositionsRemaining) {
1074   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
1075   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
1076   window1_state->set_window_position_managed(true);
1077   gfx::Rect desktop_area = window1->parent()->bounds();
1078
1079   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
1080   wm::WindowState* window2_state = wm::GetWindowState(window2.get());
1081   window2_state->set_window_position_managed(true);
1082   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
1083
1084   window1_state->Maximize();
1085   window1_state->Minimize();
1086
1087   // |window2| should be centered now.
1088   EXPECT_TRUE(window2->IsVisible());
1089   EXPECT_TRUE(window2_state->IsNormalStateType());
1090   EXPECT_EQ(base::IntToString(
1091                 (desktop_area.width() - window2->bounds().width()) / 2) +
1092             ",48 256x512", window2->bounds().ToString());
1093 }
1094
1095 // Test that nomral, maximize, minimizing will repos the remaining.
1096 TEST_F(WorkspaceControllerTest, NormToMaxToMinRepositionsRemaining) {
1097   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
1098   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
1099   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
1100   window1_state->set_window_position_managed(true);
1101   gfx::Rect desktop_area = window1->parent()->bounds();
1102
1103   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
1104   wm::WindowState* window2_state = wm::GetWindowState(window2.get());
1105   window2_state->set_window_position_managed(true);
1106   window2->SetBounds(gfx::Rect(32, 40, 256, 512));
1107
1108   // Trigger the auto window placement function by showing (and hiding) it.
1109   window1->Hide();
1110   window1->Show();
1111
1112   // |window1| should be flush right and |window3| flush left.
1113   EXPECT_EQ(base::IntToString(
1114                 desktop_area.width() - window1->bounds().width()) +
1115             ",32 640x320", window1->bounds().ToString());
1116   EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
1117
1118   window1_state->Maximize();
1119   window1_state->Minimize();
1120
1121   // |window2| should be centered now.
1122   EXPECT_TRUE(window2->IsVisible());
1123   EXPECT_TRUE(window2_state->IsNormalStateType());
1124   EXPECT_EQ(base::IntToString(
1125                 (desktop_area.width() - window2->bounds().width()) / 2) +
1126             ",40 256x512", window2->bounds().ToString());
1127 }
1128
1129 // Test that nomral, maximize, normal will repos the remaining.
1130 TEST_F(WorkspaceControllerTest, NormToMaxToNormRepositionsRemaining) {
1131   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
1132   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
1133   wm::WindowState* window1_state = wm::GetWindowState(window1.get());
1134   window1_state->set_window_position_managed(true);
1135   gfx::Rect desktop_area = window1->parent()->bounds();
1136
1137   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
1138   wm::GetWindowState(window2.get())->set_window_position_managed(true);
1139   window2->SetBounds(gfx::Rect(32, 40, 256, 512));
1140
1141   // Trigger the auto window placement function by showing (and hiding) it.
1142   window1->Hide();
1143   window1->Show();
1144
1145   // |window1| should be flush right and |window3| flush left.
1146   EXPECT_EQ(base::IntToString(
1147                 desktop_area.width() - window1->bounds().width()) +
1148             ",32 640x320", window1->bounds().ToString());
1149   EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
1150
1151   window1_state->Maximize();
1152   window1_state->Restore();
1153
1154   // |window1| should be flush right and |window2| flush left.
1155   EXPECT_EQ(base::IntToString(
1156                 desktop_area.width() - window1->bounds().width()) +
1157             ",32 640x320", window1->bounds().ToString());
1158   EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
1159 }
1160
1161 // Test that animations are triggered.
1162 TEST_F(WorkspaceControllerTest, AnimatedNormToMaxToNormRepositionsRemaining) {
1163   ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1164       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1165   scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
1166   window1->Hide();
1167   window1->SetBounds(gfx::Rect(16, 32, 640, 320));
1168   gfx::Rect desktop_area = window1->parent()->bounds();
1169   scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
1170   window2->Hide();
1171   window2->SetBounds(gfx::Rect(32, 48, 256, 512));
1172
1173   wm::GetWindowState(window1.get())->set_window_position_managed(true);
1174   wm::GetWindowState(window2.get())->set_window_position_managed(true);
1175   // Make sure nothing is animating.
1176   window1->layer()->GetAnimator()->StopAnimating();
1177   window2->layer()->GetAnimator()->StopAnimating();
1178   window2->Show();
1179
1180   // The second window should now animate.
1181   EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
1182   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
1183   window2->layer()->GetAnimator()->StopAnimating();
1184
1185   window1->Show();
1186   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
1187   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
1188
1189   window1->layer()->GetAnimator()->StopAnimating();
1190   window2->layer()->GetAnimator()->StopAnimating();
1191   // |window1| should be flush right and |window2| flush left.
1192   EXPECT_EQ(base::IntToString(
1193                 desktop_area.width() - window1->bounds().width()) +
1194             ",32 640x320", window1->bounds().ToString());
1195   EXPECT_EQ("0,48 256x512", window2->bounds().ToString());
1196 }
1197
1198 // This tests simulates a browser and an app and verifies the ordering of the
1199 // windows and layers doesn't get out of sync as various operations occur. Its
1200 // really testing code in FocusController, but easier to simulate here. Just as
1201 // with a real browser the browser here has a transient child window
1202 // (corresponds to the status bubble).
1203 TEST_F(WorkspaceControllerTest, VerifyLayerOrdering) {
1204   scoped_ptr<Window> browser(aura::test::CreateTestWindowWithDelegate(
1205       NULL, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 6, 7, 8), NULL));
1206   browser->SetName("browser");
1207   ParentWindowInPrimaryRootWindow(browser.get());
1208   browser->Show();
1209   wm::ActivateWindow(browser.get());
1210
1211   // |status_bubble| is made a transient child of |browser| and as a result
1212   // owned by |browser|.
1213   aura::test::TestWindowDelegate* status_bubble_delegate =
1214       aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate();
1215   status_bubble_delegate->set_can_focus(false);
1216   Window* status_bubble =
1217       aura::test::CreateTestWindowWithDelegate(status_bubble_delegate,
1218                                                ui::wm::WINDOW_TYPE_POPUP,
1219                                                gfx::Rect(5, 6, 7, 8),
1220                                                NULL);
1221   ::wm::AddTransientChild(browser.get(), status_bubble);
1222   ParentWindowInPrimaryRootWindow(status_bubble);
1223   status_bubble->SetName("status_bubble");
1224
1225   scoped_ptr<Window> app(aura::test::CreateTestWindowWithDelegate(
1226       NULL, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 6, 7, 8), NULL));
1227   app->SetName("app");
1228   ParentWindowInPrimaryRootWindow(app.get());
1229
1230   aura::Window* parent = browser->parent();
1231
1232   app->Show();
1233   wm::ActivateWindow(app.get());
1234   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1235
1236   // Minimize the app, focus should go the browser.
1237   app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1238   EXPECT_TRUE(wm::IsActiveWindow(browser.get()));
1239   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1240
1241   // Minimize the browser (neither windows are focused).
1242   browser->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1243   EXPECT_FALSE(wm::IsActiveWindow(browser.get()));
1244   EXPECT_FALSE(wm::IsActiveWindow(app.get()));
1245   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1246
1247   // Show the browser (which should restore it).
1248   browser->Show();
1249   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1250
1251   // Activate the browser.
1252   ash::wm::ActivateWindow(browser.get());
1253   EXPECT_TRUE(wm::IsActiveWindow(browser.get()));
1254   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1255
1256   // Restore the app. This differs from above code for |browser| as internally
1257   // the app code does this. Restoring this way or using Show() should not make
1258   // a difference.
1259   app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
1260   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1261
1262   // Activate the app.
1263   ash::wm::ActivateWindow(app.get());
1264   EXPECT_TRUE(wm::IsActiveWindow(app.get()));
1265   EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
1266 }
1267
1268 namespace {
1269
1270 // Used by DragMaximizedNonTrackedWindow to track how many times the window
1271 // hierarchy changes affecting the specified window.
1272 class DragMaximizedNonTrackedWindowObserver
1273     : public aura::WindowObserver {
1274  public:
1275   DragMaximizedNonTrackedWindowObserver(aura::Window* window)
1276   : change_count_(0),
1277     window_(window) {
1278   }
1279
1280   // Number of times OnWindowHierarchyChanged() has been received.
1281   void clear_change_count() { change_count_ = 0; }
1282   int change_count() const {
1283     return change_count_;
1284   }
1285
1286   // aura::WindowObserver overrides:
1287   // Counts number of times a window is reparented. Ignores reparenting into and
1288   // from a docked container which is expected when a tab is dragged.
1289   virtual void OnWindowHierarchyChanged(
1290       const HierarchyChangeParams& params) OVERRIDE {
1291     if (params.target != window_ ||
1292         (params.old_parent->id() == kShellWindowId_DefaultContainer &&
1293          params.new_parent->id() == kShellWindowId_DockedContainer) ||
1294         (params.old_parent->id() == kShellWindowId_DockedContainer &&
1295          params.new_parent->id() == kShellWindowId_DefaultContainer)) {
1296       return;
1297     }
1298     change_count_++;
1299   }
1300
1301  private:
1302   int change_count_;
1303   aura::Window* window_;
1304
1305   DISALLOW_COPY_AND_ASSIGN(DragMaximizedNonTrackedWindowObserver);
1306 };
1307
1308 }  // namespace
1309
1310 // Verifies that a new maximized window becomes visible after its activation
1311 // is requested, even though it does not become activated because a system
1312 // modal window is active.
1313 TEST_F(WorkspaceControllerTest, SwitchFromModal) {
1314   scoped_ptr<Window> modal_window(CreateTestWindowUnparented());
1315   modal_window->SetBounds(gfx::Rect(10, 11, 21, 22));
1316   modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
1317   ParentWindowInPrimaryRootWindow(modal_window.get());
1318   modal_window->Show();
1319   wm::ActivateWindow(modal_window.get());
1320
1321   scoped_ptr<Window> maximized_window(CreateTestWindow());
1322   maximized_window->SetProperty(
1323       aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1324   maximized_window->Show();
1325   wm::ActivateWindow(maximized_window.get());
1326   EXPECT_TRUE(maximized_window->IsVisible());
1327 }
1328
1329 namespace {
1330
1331 // Subclass of WorkspaceControllerTest that runs tests with docked windows
1332 // enabled and disabled.
1333 class WorkspaceControllerTestDragging
1334     : public WorkspaceControllerTest,
1335       public testing::WithParamInterface<bool> {
1336  public:
1337   WorkspaceControllerTestDragging() {}
1338   virtual ~WorkspaceControllerTestDragging() {}
1339
1340   // testing::Test:
1341   virtual void SetUp() OVERRIDE {
1342     WorkspaceControllerTest::SetUp();
1343     if (!docked_windows_enabled()) {
1344       CommandLine::ForCurrentProcess()->AppendSwitch(
1345           ash::switches::kAshDisableDockedWindows);
1346     }
1347   }
1348
1349   bool docked_windows_enabled() const { return GetParam(); }
1350
1351  private:
1352   DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestDragging);
1353 };
1354
1355 }  // namespace
1356
1357 // Verifies that when dragging a window over the shelf overlap is detected
1358 // during and after the drag.
1359 TEST_P(WorkspaceControllerTestDragging, DragWindowOverlapShelf) {
1360   aura::test::TestWindowDelegate delegate;
1361   delegate.set_window_component(HTCAPTION);
1362   scoped_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate(
1363       &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL));
1364   ParentWindowInPrimaryRootWindow(w1.get());
1365
1366   ShelfLayoutManager* shelf = shelf_layout_manager();
1367   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1368
1369   // Drag near the shelf.
1370   aura::test::EventGenerator generator(
1371       Shell::GetPrimaryRootWindow(), gfx::Point());
1372   generator.MoveMouseTo(10, 10);
1373   generator.PressLeftButton();
1374   generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 70);
1375
1376   // Shelf should not be in overlapped state.
1377   EXPECT_FALSE(GetWindowOverlapsShelf());
1378
1379   generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 20);
1380
1381   // Shelf should detect overlap. Overlap state stays after mouse is released.
1382   EXPECT_TRUE(GetWindowOverlapsShelf());
1383   generator.ReleaseLeftButton();
1384   EXPECT_TRUE(GetWindowOverlapsShelf());
1385 }
1386
1387 // Verifies that when dragging a window autohidden shelf stays hidden during
1388 // and after the drag.
1389 TEST_P(WorkspaceControllerTestDragging, DragWindowKeepsShelfAutohidden) {
1390   aura::test::TestWindowDelegate delegate;
1391   delegate.set_window_component(HTCAPTION);
1392   scoped_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate(
1393       &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL));
1394   ParentWindowInPrimaryRootWindow(w1.get());
1395
1396   ShelfLayoutManager* shelf = shelf_layout_manager();
1397   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1398   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1399
1400   // Drag very little.
1401   aura::test::EventGenerator generator(
1402       Shell::GetPrimaryRootWindow(), gfx::Point());
1403   generator.MoveMouseTo(10, 10);
1404   generator.PressLeftButton();
1405   generator.MoveMouseTo(12, 12);
1406
1407   // Shelf should be hidden during and after the drag.
1408   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1409   generator.ReleaseLeftButton();
1410   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1411 }
1412
1413 INSTANTIATE_TEST_CASE_P(DockedOrNot, WorkspaceControllerTestDragging,
1414                         ::testing::Bool());
1415
1416 // Verifies that events are targeted properly just outside the window edges.
1417 TEST_F(WorkspaceControllerTest, WindowEdgeHitTest) {
1418   aura::test::TestWindowDelegate d_first, d_second;
1419   scoped_ptr<Window> first(aura::test::CreateTestWindowWithDelegate(&d_first,
1420       123, gfx::Rect(20, 10, 100, 50), NULL));
1421   ParentWindowInPrimaryRootWindow(first.get());
1422   first->Show();
1423
1424   scoped_ptr<Window> second(aura::test::CreateTestWindowWithDelegate(&d_second,
1425       234, gfx::Rect(30, 40, 40, 10), NULL));
1426   ParentWindowInPrimaryRootWindow(second.get());
1427   second->Show();
1428
1429   ui::EventTarget* root = first->GetRootWindow();
1430   ui::EventTargeter* targeter = root->GetEventTargeter();
1431
1432   // The windows overlap, and |second| is on top of |first|. Events targeted
1433   // slightly outside the edges of the |second| window should still be targeted
1434   // to |second| to allow resizing the windows easily.
1435
1436   const int kNumPoints = 4;
1437   struct {
1438     const char* direction;
1439     gfx::Point location;
1440   } points[kNumPoints] = {
1441     { "left", gfx::Point(28, 45) },  // outside the left edge.
1442     { "top", gfx::Point(50, 38) },  // outside the top edge.
1443     { "right", gfx::Point(72, 45) },  // outside the right edge.
1444     { "bottom", gfx::Point(50, 52) },  // outside the bottom edge.
1445   };
1446   // Do two iterations, first without any transform on |second|, and the second
1447   // time after applying some transform on |second| so that it doesn't get
1448   // targeted.
1449   for (int times = 0; times < 2; ++times) {
1450     SCOPED_TRACE(times == 0 ? "Without transform" : "With transform");
1451     aura::Window* expected_target = times == 0 ? second.get() : first.get();
1452     for (int i = 0; i < kNumPoints; ++i) {
1453       SCOPED_TRACE(points[i].direction);
1454       const gfx::Point& location = points[i].location;
1455       ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
1456                            ui::EF_NONE);
1457       ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
1458       EXPECT_EQ(expected_target, target);
1459
1460       ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
1461                            ui::EventTimeForNow());
1462       target = targeter->FindTargetForEvent(root, &touch);
1463       EXPECT_EQ(expected_target, target);
1464     }
1465     // Apply a transform on |second|. After the transform is applied, the window
1466     // should no longer be targeted.
1467     gfx::Transform transform;
1468     transform.Translate(70, 40);
1469     second->SetTransform(transform);
1470   }
1471 }
1472
1473 // Verifies events targeting just outside the window edges for panels.
1474 TEST_F(WorkspaceControllerTest, WindowEdgeHitTestPanel) {
1475   aura::test::TestWindowDelegate delegate;
1476   scoped_ptr<Window> window(CreateTestPanel(&delegate,
1477                                            gfx::Rect(20, 10, 100, 50)));
1478   ui::EventTarget* root = window->GetRootWindow();
1479   ui::EventTargeter* targeter = root->GetEventTargeter();
1480   const gfx::Rect bounds = window->bounds();
1481   const int kNumPoints = 5;
1482   struct {
1483     const char* direction;
1484     gfx::Point location;
1485     bool is_target_hit;
1486   } points[kNumPoints] = {
1487     { "left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true },
1488     { "top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true },
1489     { "right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true },
1490     { "bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), true },
1491     { "outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false },
1492   };
1493   for (int i = 0; i < kNumPoints; ++i) {
1494     SCOPED_TRACE(points[i].direction);
1495     const gfx::Point& location = points[i].location;
1496     ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
1497                          ui::EF_NONE);
1498     ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
1499     if (points[i].is_target_hit)
1500       EXPECT_EQ(window.get(), target);
1501     else
1502       EXPECT_NE(window.get(), target);
1503
1504     ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
1505                          ui::EventTimeForNow());
1506     target = targeter->FindTargetForEvent(root, &touch);
1507     if (points[i].is_target_hit)
1508       EXPECT_EQ(window.get(), target);
1509     else
1510       EXPECT_NE(window.get(), target);
1511   }
1512 }
1513
1514 // Verifies events targeting just outside the window edges for docked windows.
1515 TEST_F(WorkspaceControllerTest, WindowEdgeHitTestDocked) {
1516   if (!switches::UseDockedWindows())
1517     return;
1518   aura::test::TestWindowDelegate delegate;
1519   // Make window smaller than the minimum docked area so that the window edges
1520   // are exposed.
1521   delegate.set_maximum_size(gfx::Size(180, 200));
1522   scoped_ptr<Window> window(aura::test::CreateTestWindowWithDelegate(&delegate,
1523       123, gfx::Rect(20, 10, 100, 50), NULL));
1524   ParentWindowInPrimaryRootWindow(window.get());
1525   aura::Window* docked_container = Shell::GetContainer(
1526       window->GetRootWindow(), internal::kShellWindowId_DockedContainer);
1527   docked_container->AddChild(window.get());
1528   window->Show();
1529   ui::EventTarget* root = window->GetRootWindow();
1530   ui::EventTargeter* targeter = root->GetEventTargeter();
1531   const gfx::Rect bounds = window->bounds();
1532   const int kNumPoints = 5;
1533   struct {
1534     const char* direction;
1535     gfx::Point location;
1536     bool is_target_hit;
1537   } points[kNumPoints] = {
1538     { "left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true },
1539     { "top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true },
1540     { "right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true },
1541     { "bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), true },
1542     { "outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false },
1543   };
1544   for (int i = 0; i < kNumPoints; ++i) {
1545     SCOPED_TRACE(points[i].direction);
1546     const gfx::Point& location = points[i].location;
1547     ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
1548                          ui::EF_NONE);
1549     ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
1550     if (points[i].is_target_hit)
1551       EXPECT_EQ(window.get(), target);
1552     else
1553       EXPECT_NE(window.get(), target);
1554
1555     ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
1556                          ui::EventTimeForNow());
1557     target = targeter->FindTargetForEvent(root, &touch);
1558     if (points[i].is_target_hit)
1559       EXPECT_EQ(window.get(), target);
1560     else
1561       EXPECT_NE(window.get(), target);
1562   }
1563 }
1564
1565 }  // namespace internal
1566 }  // namespace ash