1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ash/wm/workspace_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/root_window_controller.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_widget.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/status_area_widget.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/ash_test_base.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/test/shell_test_api.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/test/test_shelf_delegate.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/panels/panel_layout_manager.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/wm/workspace/workspace_window_resizer.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_window_delegate.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/hit_test.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_types.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_animation_duration_scale_mode.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/events/event_utils.h"
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/test/event_generator.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_animations.h"
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using aura::Window;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns a string containing the names of all the children of |window| (in
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// order). Each entry is separated by a space.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetWindowNames(const aura::Window* window) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string result;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < window->children().size(); ++i) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i != 0)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result += " ";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result += window->children()[i]->name();
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns a string containing the names of windows corresponding to each of the
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// child layers of |window|'s layer. Any layers that don't correspond to a child
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Window of |window| are ignored. The result is ordered based on the layer
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ordering.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetLayerNames(const aura::Window* window) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<const ui::Layer*, std::string> LayerToWindowNameMap;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerToWindowNameMap window_names;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < window->children().size(); ++i) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window_names[window->children()[i]->layer()] =
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window->children()[i]->name();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string result;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<ui::Layer*>& layers(window->layer()->children());
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < layers.size(); ++i) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerToWindowNameMap::iterator layer_i =
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_names.find(layers[i]);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (layer_i != window_names.end()) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!result.empty())
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result += " ";
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result += layer_i->second;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class WorkspaceControllerTest : public test::AshTestBase {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  WorkspaceControllerTest() {}
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual ~WorkspaceControllerTest() {}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* CreateTestWindowUnparented() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* window = new aura::Window(NULL);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->Init(aura::WINDOW_LAYER_TEXTURED);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return window;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* CreateTestWindow() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* window = new aura::Window(NULL);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->Init(aura::WINDOW_LAYER_TEXTURED);
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ParentWindowInPrimaryRootWindow(window);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return window;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  aura::Window* CreateBrowserLikeWindow(const gfx::Rect& bounds) {
105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    aura::Window* window = CreateTestWindow();
106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    window->SetBounds(bounds);
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    wm::WindowState* window_state = wm::GetWindowState(window);
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    window_state->set_window_position_managed(true);
109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    window->Show();
110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return window;
111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  aura::Window* CreatePopupLikeWindow(const gfx::Rect& bounds) {
114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    aura::Window* window = CreateTestWindowInShellWithBounds(bounds);
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    window->Show();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return window;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* CreateTestPanel(aura::WindowDelegate* delegate,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const gfx::Rect& bounds) {
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate,
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::wm::WINDOW_TYPE_PANEL,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        0,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bounds);
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    test::TestShelfDelegate* shelf_delegate =
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        test::TestShelfDelegate::instance();
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    shelf_delegate->AddShelfItem(window);
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    PanelLayoutManager* manager = static_cast<PanelLayoutManager*>(
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        Shell::GetContainer(window->GetRootWindow(),
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                            kShellWindowId_PanelContainer)->layout_manager());
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    manager->Relayout();
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return window;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  aura::Window* GetDesktop() {
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
1382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                               kShellWindowId_DefaultContainer);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect GetFullscreenBounds(aura::Window* window) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Shell::GetScreen()->GetDisplayNearestWindow(window).bounds();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShelfWidget* shelf_widget() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Shell::GetPrimaryRootWindowController()->shelf();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShelfLayoutManager* shelf_layout_manager() {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetWindowOverlapsShelf() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return shelf_layout_manager()->window_overlaps_shelf();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTest);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions around adding a normal window.
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, AddNormalWindowWhenEmpty) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(0, 0, 250, 251));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window_state = wm::GetWindowState(w1.get());
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window_state->HasRestoreBounds());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window_state->HasRestoreBounds());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(w1->layer() != NULL);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->visible());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions around maximizing/unmaximizing.
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, SingleMaximizeWindow) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(0, 0, 250, 251));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(w1->layer() != NULL);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->visible());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maximize the window.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()).width(),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            w1->bounds().width());
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()).height(),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            w1->bounds().height());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore the window.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// Assertions around two windows and toggling one to be fullscreen.
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, FullscreenWithNormalWindow) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(0, 0, 250, 251));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(w1->layer() != NULL);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->visible());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetBounds(gfx::Rect(0, 0, 50, 51));
2265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
230a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // Both windows should be in the same workspace.
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w2.get(), GetDesktop()->children()[1]);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  gfx::Rect work_area(
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScreenUtil::GetMaximizedWindowBoundsInParent(w1.get()));
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(work_area.width(), w2->bounds().width());
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(work_area.height(), w2->bounds().height());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore w2, which should then go back to one workspace.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(50, w2->bounds().width());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(51, w2->bounds().height());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Makes sure requests to change the bounds of a normal window go through.
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, ChangeBoundsOfNormalWindow) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setting the bounds should go through since the window is in the normal
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // workspace.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(0, 0, 200, 500));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(200, w1->bounds().width());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(500, w1->bounds().height());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies the bounds is not altered when showing and grid is enabled.
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, SnapToGrid) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindowUnparented());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(1, 6, 25, 30));
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(w1.get());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We are not aligning this anymore this way. When the window gets shown
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the window is expected to be handled differently, but this cannot be
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tested with this test. So the result of this test should be that the
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bounds are exactly as passed in.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("1,6 25x30", w1->bounds().ToString());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions around a fullscreen window.
271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, SingleFullscreenWindow) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(0, 0, 250, 251));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the window fullscreen.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width());
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore the window. Use SHOW_STATE_DEFAULT as that is what we'll end up
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with when using views::Widget.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_DEFAULT);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 250x251", w1->bounds().ToString());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(250, w1->bounds().width());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(251, w1->bounds().height());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Back to fullscreen.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[0]);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GetFullscreenBounds(w1.get()).width(), w1->bounds().width());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GetFullscreenBounds(w1.get()).height(), w1->bounds().height());
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window_state = wm::GetWindowState(w1.get());
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ASSERT_TRUE(window_state->HasRestoreBounds());
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ("0,0 250x251", window_state->GetRestoreBoundsInScreen().ToString());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions around minimizing a single window.
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, MinimizeSingleWindow) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(w1->layer()->IsDrawn());
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->GetTargetTransform().IsIdentity());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Show the window.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(wm::GetWindowState(w1.get())->IsNormalStateType());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->IsDrawn());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// Assertions around minimizing a fullscreen window.
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, MinimizeFullscreenWindow) {
3215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Two windows, w1 normal, w2 fullscreen.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
3255e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* w1_state = wm::GetWindowState(w1.get());
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* w2_state = wm::GetWindowState(w2.get());
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w2_state->Activate();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Minimize w2.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->layer()->IsDrawn());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(w2->layer()->IsDrawn());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Show the window, which should trigger unminimizing.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w2_state->Activate();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(w2_state->IsFullscreen());
343a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  EXPECT_TRUE(w1->layer()->IsDrawn());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w2->layer()->IsDrawn());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
346a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // Minimize the window, which should hide the window.
34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(w2_state->IsActive());
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w2_state->Minimize();
34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(w2_state->IsActive());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(w2->layer()->IsDrawn());
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(w1_state->IsActive());
35223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(w2.get(), GetDesktop()->children()[0]);
35323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[1]);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the window normal.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
35723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Setting back to normal doesn't change the activation.
35823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_FALSE(w2_state->IsActive());
35923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_TRUE(w1_state->IsActive());
36023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(w2.get(), GetDesktop()->children()[0]);
36123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(w1.get(), GetDesktop()->children()[1]);
362a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  EXPECT_TRUE(w2->layer()->IsDrawn());
363a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
364a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies ShelfLayoutManager's visibility/auto-hide state is correctly
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updated.
367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, ShelfStateUpdated) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since ShelfLayoutManager queries for mouse location, move the mouse so
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it isn't over the shelf.
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     gfx::Point());
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.MoveMouseTo(0, 0);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect w1_bounds(0, 1, 101, 102);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect touches_shelf_bounds(
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, shelf->GetIdealBounds().y() - 10, 101, 102);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move |w1| to overlap the shelf.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(touches_shelf_bounds);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A visible ignored window should not trigger the overlap.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w_ignored(CreateTestWindow());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w_ignored->SetBounds(touches_shelf_bounds);
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(&(*w_ignored))->set_ignored_by_shelf(true);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w_ignored->Show();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make it visible, since visible shelf overlaps should be true.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetWindowOverlapsShelf());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(w1_bounds);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maximize the window.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fullscreen.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normal.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move window so it obscures shelf.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(touches_shelf_bounds);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetWindowOverlapsShelf());
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move it back.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(w1_bounds);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maximize again.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Minimize.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the restore from minimize will restore to the pre-minimize
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // state (tested elsewhere), we abandon the current size and restore
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rect and set them to the window.
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window_state = wm::GetWindowState(w1.get());
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect restore = window_state->GetRestoreBoundsInScreen();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 800x597", w1->bounds().ToString());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", restore.ToString());
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_state->ClearRestoreBounds();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(restore);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create another window, maximized.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetBounds(gfx::Rect(10, 11, 250, 251));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                w2->parent()).ToString(),
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            w2->bounds().ToString());
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch to w1.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                w2->parent()).ToString(),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            w2->bounds().ToString());
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch to w2.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,1 101x102", w1->bounds().ToString());
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(ScreenUtil::GetMaximizedWindowBoundsInParent(w2.get()).ToString(),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            w2->bounds().ToString());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Turn off auto-hide, switch back to w2 (maximized) and verify overlap.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move w1 to overlap shelf, it shouldn't change window overlaps shelf since
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the window isn't in the visible workspace.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(touches_shelf_bounds);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Activate w1. Although w1 is visible, the overlap state is still false since
4955e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // w2 is maximized.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
4975e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
4985e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
4995e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Restore w2.
5005e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetWindowOverlapsShelf());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies going from maximized to minimized sets the right state for painting
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the background of the launcher.
506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, MinimizeResetsVisibility) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, shelf_widget()->GetBackgroundType());
5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SHELF_VISIBLE,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            shelf_layout_manager()->visibility_state());
5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, shelf_widget()->GetBackgroundType());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies window visibility during various workspace changes.
520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, VisibilityTests) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Create another window, activate it and make it fullscreen.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
5305e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w2->IsVisible());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
533a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  EXPECT_TRUE(w1->IsVisible());
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // Switch to w1. |w1| should be visible on top of |w2|.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
539a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  EXPECT_TRUE(w2->IsVisible());
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch back to |w2|.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w2->IsVisible());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
545a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  EXPECT_TRUE(w1->IsVisible());
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore |w2|, both windows should be visible.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w2->IsVisible());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Make |w2| fullscreen again, then close it.
5555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Hide();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(w2->IsVisible());
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Create |w2| and maximize it.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2.reset(CreateTestWindow());
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
5655e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w2->IsVisible());
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w2->layer()->GetCombinedOpacity());
5685e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close |w2|.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2.reset();
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, w1->layer()->GetCombinedOpacity());
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(w1->IsVisible());
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies windows that are offscreen don't move when switching workspaces.
577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, DontMoveOnSwitch) {
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     gfx::Point());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.MoveMouseTo(0, 0);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect touches_shelf_bounds(
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, shelf->GetIdealBounds().y() - 10, 101, 102);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move |w1| to overlap the shelf.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(touches_shelf_bounds);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create another window and maximize it.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetBounds(gfx::Rect(10, 11, 250, 251));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch to w1.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(touches_shelf_bounds.ToString(), w1->bounds().ToString());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that windows that are completely offscreen move when switching
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// workspaces.
605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, MoveOnSwitch) {
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     gfx::Point());
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.MoveMouseTo(0, 0);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindow());
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect w1_bounds(0, shelf->GetIdealBounds().y(), 100, 200);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move |w1| so that the top edge is the same as the top edge of the shelf.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(w1_bounds);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(w1_bounds.ToString(), w1->bounds().ToString());
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create another window and maximize it.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetBounds(gfx::Rect(10, 11, 250, 251));
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Increase the size of the WorkAreaInsets. This would make |w1| fall
62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // completely out of the display work area.
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gfx::Insets insets =
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Shell::GetScreen()->GetPrimaryDisplay().GetWorkAreaInsets();
63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  insets.Set(0, 0, insets.bottom() + 30, 0);
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Shell::GetInstance()->SetDisplayWorkAreaInsets(w1.get(), insets);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch to w1. The window should have moved.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(w1_bounds.ToString(), w1->bounds().ToString());
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowDelegate used by DontCrashOnChangeAndActivate.
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DontCrashOnChangeAndActivateDelegate
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public aura::test::TestWindowDelegate {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DontCrashOnChangeAndActivateDelegate() : window_(NULL) {}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_window(aura::Window* window) { window_ = window; }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WindowDelegate overrides:
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Rect& new_bounds) OVERRIDE {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window_) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wm::ActivateWindow(window_);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_ = NULL;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* window_;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DontCrashOnChangeAndActivateDelegate);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exercises possible crash in W2. Here's the sequence:
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . minimize a maximized window.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . remove the window (which happens when switching displays).
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . add the window back.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . show the window and during the bounds change activate it.
670a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, DontCrashOnChangeAndActivate) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force the shelf
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DontCrashOnChangeAndActivateDelegate delegate;
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindowInShellWithDelegate(
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &delegate, 1000, gfx::Rect(10, 11, 250, 251)));
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
68068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* w1_state = wm::GetWindowState(w1.get());
68168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w1_state->Activate();
68268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w1_state->Maximize();
68368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  w1_state->Minimize();
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->parent()->RemoveChild(w1.get());
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do this so that when we Show() the window a resize occurs and we make the
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window active.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(w1.get());
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.set_window(w1.get());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies a window with a transient parent not managed by workspace works.
697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, TransientParent) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Normal window with no transient parent.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w2(CreateTestWindow());
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->SetBounds(gfx::Rect(10, 11, 250, 251));
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->Show();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w2.get());
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Window with a transient parent. We set the transient parent to the root,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which would never happen but is enough to exercise the bug.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Window> w1(CreateTestWindowUnparented());
707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::AddTransientChild(
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Shell::GetInstance()->GetPrimaryRootWindow(), w1.get());
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->SetBounds(gfx::Rect(10, 11, 250, 251));
7101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(w1.get());
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->Show();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wm::ActivateWindow(w1.get());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The window with the transient parent should get added to the same parent as
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the normal window.
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(w2->parent(), w1->parent());
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
719424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Test the placement of newly created windows.
720424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnCreate) {
721424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!SupportsHostWindowResize())
722424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
723424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  UpdateDisplay("1600x1200");
724424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Creating a popup handler here to make sure it does not interfere with the
725424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // existing windows.
726424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gfx::Rect source_browser_bounds(16, 32, 640, 320);
727424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<aura::Window> browser_window(CreateBrowserLikeWindow(
728424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      source_browser_bounds));
729424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
730424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Creating a popup to make sure it does not interfere with the positioning.
731424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<aura::Window> browser_popup(CreatePopupLikeWindow(
732424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      gfx::Rect(16, 32, 128, 256)));
733424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
734424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  browser_window->Show();
735424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  browser_popup->Show();
736424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
737424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  { // With a shown window it's size should get returned.
738424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
739424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        source_browser_bounds));
740424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // The position should be right flush.
741424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("960,32 640x320", new_browser_window->bounds().ToString());
742424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
743424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
744424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  { // With the window shown - but more on the right side then on the left
745424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // side (and partially out of the screen), it should default to the other
746424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // side and inside the screen.
747424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    gfx::Rect source_browser_bounds(gfx::Rect(1000, 600, 640, 320));
748424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    browser_window->SetBounds(source_browser_bounds);
749424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
750424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
751424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        source_browser_bounds));
752424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // The position should be left & bottom flush.
753424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("0,600 640x320", new_browser_window->bounds().ToString());
754424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
755424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // If the other window was already beyond the point to get right flush
756424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // it will remain where it is.
757424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("1000,600 640x320", browser_window->bounds().ToString());
758424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
759424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
760424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  { // Make sure that popups do not get changed.
761424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<aura::Window> new_popup_window(CreatePopupLikeWindow(
762424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        gfx::Rect(50, 100, 300, 150)));
763424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("50,100 300x150", new_popup_window->bounds().ToString());
764424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
765424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
766424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  browser_window->Hide();
767424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  { // If a window is there but not shown the default should be centered.
768424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<aura::Window> new_browser_window(CreateBrowserLikeWindow(
769424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        gfx::Rect(50, 100, 300, 150)));
770424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("650,100 300x150", new_browser_window->bounds().ToString());
771424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
772424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
773424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
774a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Test that adding a second window shifts both the first window and its
775a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// transient child.
776a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochTEST_F(WorkspaceControllerTest, AutoPlacingMovesTransientChild) {
777a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create an auto-positioned window.
778a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
779a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect desktop_area = window1->parent()->bounds();
780a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  wm::GetWindowState(window1.get())->set_window_position_managed(true);
781a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Hide and then show |window1| to trigger auto-positioning logic.
782a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window1->Hide();
783a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window1->SetBounds(gfx::Rect(16, 32, 300, 300));
784a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window1->Show();
785a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
786a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // |window1| should be horizontally centered.
787a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int x_window1 = (desktop_area.width() - 300) / 2;
788a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  EXPECT_EQ(base::IntToString(x_window1) + ",32 300x300",
789a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            window1->bounds().ToString());
790a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
791a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create a |child| window and make it a transient child of |window1|.
792a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<Window> child(CreateTestWindowUnparented());
793a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ::wm::AddTransientChild(window1.get(), child.get());
794a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const int x_child = x_window1 + 50;
795a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  child->SetBounds(gfx::Rect(x_child, 20, 200, 200));
796a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ParentWindowInPrimaryRootWindow(child.get());
797a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  child->Show();
798a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  wm::ActivateWindow(child.get());
799a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
800a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The |child| should be where it was created.
801a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  EXPECT_EQ(base::IntToString(x_child) + ",20 200x200",
802a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            child->bounds().ToString());
803a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
804a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create and show a second window forcing the first window and its child to
805a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // move.
806a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
807a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  wm::GetWindowState(window2.get())->set_window_position_managed(true);
808a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Hide and then show |window2| to trigger auto-positioning logic.
809a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window2->Hide();
810a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window2->SetBounds(gfx::Rect(32, 48, 250, 250));
811a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  window2->Show();
812a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
813a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Check that both |window1| and |child| have moved left.
814a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  EXPECT_EQ("0,32 300x300", window1->bounds().ToString());
815a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int x = x_child - x_window1;
816a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  EXPECT_EQ(base::IntToString(x) + ",20 200x200", child->bounds().ToString());
817a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Check that |window2| has moved right.
818a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  x = desktop_area.width() - window2->bounds().width();
819a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  EXPECT_EQ(base::IntToString(x) + ",48 250x250", window2->bounds().ToString());
820a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
821a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the basic auto placement of one and or two windows in a "simulated
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// session" of sequential window operations.
824424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnShowHide) {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test 1: In case there is no manageable window, no window should shift.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trigger the auto window placement function by making it visible.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the bounds are getting changed while it is invisible.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Show();
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the initial position of the windows is unchanged.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("32,48 256x512", window2->bounds().ToString());
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the second window and make sure that the first window
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // does NOT get centered.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2.reset();
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test 2: Set up two managed windows and check their auto positioning.
84968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
85058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(2));
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window3.get())->set_window_position_managed(true);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To avoid any auto window manager changes due to SetBounds, the window
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gets first hidden and then shown again.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window3->Hide();
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window3->SetBounds(gfx::Rect(32, 48, 256, 512));
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window3->Show();
858d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |window1| should be flush left and |window3| flush right.
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window3->bounds().width()) +
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",48 256x512", window3->bounds().ToString());
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After removing |window3|, |window1| should be centered again.
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window3.reset();
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::IntToString(
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (desktop_area.width() - window1->bounds().width()) / 2) +
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ",32 640x320", window1->bounds().ToString());
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test 3: Set up a manageable and a non manageable window and check
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // positioning.
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window4(CreateTestWindowInShellWithId(3));
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To avoid any auto window manager changes due to SetBounds, the window
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gets first hidden and then shown again.
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window4->SetBounds(gfx::Rect(32, 48, 256, 512));
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be centered and |window4| untouched.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::IntToString(
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (desktop_area.width() - window1->bounds().width()) / 2) +
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ",32 640x320", window1->bounds().ToString());
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("32,48 256x512", window4->bounds().ToString());
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test4: A single manageable window should get centered.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window4.reset();
88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_bounds_changed_by_user(false);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trigger the auto window placement function by showing (and hiding) it.
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be centered.
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::IntToString(
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (desktop_area.width() - window1->bounds().width()) / 2) +
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ",32 640x320", window1->bounds().ToString());
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the proper usage of user window movement interaction.
901a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, TestUserMovedWindowRepositioning) {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
90968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
91068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window2_state = wm::GetWindowState(window2.get());
91168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
91268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
91368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window2_state->set_window_position_managed(true);
91468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window1_state->bounds_changed_by_user());
91568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window2_state->bounds_changed_by_user());
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the current location gets preserved if the user has
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // positioned it previously.
91968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_bounds_changed_by_user(true);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("16,32 640x320", window1->bounds().ToString());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag should be still set.
92368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(window1_state->bounds_changed_by_user());
92468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window2_state->bounds_changed_by_user());
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Turn on the second window and make sure that both windows are now
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // positionable again (user movement cleared).
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Show();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
930424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // |window1| should be flush left and |window2| flush right.
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::IntToString(desktop_area.width() - window2->bounds().width()) +
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ",48 256x512", window2->bounds().ToString());
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FLag should now be reset.
93668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window1_state->bounds_changed_by_user());
93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(window2_state->bounds_changed_by_user());
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Going back to one shown window should keep the state.
94068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_bounds_changed_by_user(true);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("0,32 640x320", window1->bounds().ToString());
94368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(window1_state->bounds_changed_by_user());
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
946424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Test if the single window will be restored at original position.
947424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(WorkspaceControllerTest, TestSingleWindowsRestoredBounds) {
948424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<aura::Window> window1(
949424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
950424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<aura::Window> window2(
951424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(110, 110, 100, 100)));
952424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<aura::Window> window3(
953424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(120, 120, 100, 100)));
954424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window1->Hide();
955424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window2->Hide();
956424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window3->Hide();
95768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window1.get())->set_window_position_managed(true);
95868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window2.get())->set_window_position_managed(true);
95968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window3.get())->set_window_position_managed(true);
960424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
961424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window1->Show();
962424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  wm::ActivateWindow(window1.get());
963424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window2->Show();
964424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  wm::ActivateWindow(window2.get());
965424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window3->Show();
966424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  wm::ActivateWindow(window3.get());
967424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, window1->bounds().x());
968424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(window2->GetRootWindow()->bounds().right(),
969424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            window2->bounds().right());
970424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, window3->bounds().x());
971424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
972424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window1->Hide();
973424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(window2->GetRootWindow()->bounds().right(),
974424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            window2->bounds().right());
975424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, window3->bounds().x());
976424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
977424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Being a single window will retore the original location.
978424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window3->Hide();
979424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  wm::ActivateWindow(window2.get());
980424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ("110,110 100x100", window2->bounds().ToString());
981424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
982424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Showing the 3rd will push the 2nd window left.
983424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window3->Show();
984424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  wm::ActivateWindow(window3.get());
985424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, window2->bounds().x());
986424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(window3->GetRootWindow()->bounds().right(),
987424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            window3->bounds().right());
988424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
989424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Being a single window will retore the original location.
990424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  window2->Hide();
991424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ("120,120 100x100", window3->bounds().ToString());
992424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
993424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that user placed windows go back to their user placement after the user
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// closes all other windows.
996a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, TestUserHandledWindowRestore) {
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect user_pos = gfx::Rect(16, 42, 640, 320);
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(user_pos);
100068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
100268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->SetPreAutoManageWindowBounds(user_pos);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a second window to let the auto manager kick in.
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
101068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window1.get())->set_window_position_managed(true);
101168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window2.get())->set_window_position_managed(true);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString());
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Show();
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |window1| should be flush left and |window2| flush right.
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("0," + base::IntToString(user_pos.y()) +
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            " 640x320", window1->bounds().ToString());
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::IntToString(desktop_area.width() - window2->bounds().width()) +
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ",48 256x512", window2->bounds().ToString());
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After the other window get hidden the window has to move back to the
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous position and the bounds should still be set and unchanged.
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString());
102768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ASSERT_TRUE(window1_state->pre_auto_manage_window_bounds());
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(user_pos.ToString(),
102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            window1_state->pre_auto_manage_window_bounds()->ToString());
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Solo window should be restored to the bounds where a user moved to.
10335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(WorkspaceControllerTest, TestRestoreToUserModifiedBounds) {
10345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!SupportsHostWindowResize())
10355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
10365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UpdateDisplay("400x300");
10385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect default_bounds(10, 0, 100, 100);
10395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<aura::Window> window1(
10405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateTestWindowInShellWithBounds(default_bounds));
10415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
10425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window1->Hide();
10435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window1_state->set_window_position_managed(true);
10445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window1->Show();
10455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // First window is centered.
10465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("150,0 100x100", window1->bounds().ToString());
10475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<aura::Window> window2(
10485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateTestWindowInShellWithBounds(default_bounds));
10495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  wm::WindowState* window2_state = wm::GetWindowState(window2.get());
10505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2->Hide();
10515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2_state->set_window_position_managed(true);
10525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2->Show();
10535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Auto positioning pushes windows to each sides.
10555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
10565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("300,0 100x100", window2->bounds().ToString());
10575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2->Hide();
10595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Restores to the center.
10605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("150,0 100x100", window1->bounds().ToString());
10615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // A user moved the window.
10635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<WindowResizer> resizer(CreateWindowResizer(
10645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      window1.get(),
10655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      gfx::Point(),
10665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      HTCAPTION,
10675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      aura::client::WINDOW_MOVE_SOURCE_MOUSE).release());
10685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Point location = resizer->GetInitialLocation();
10695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  location.Offset(-50, 0);
10705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  resizer->Drag(location, 0);
10715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  resizer->CompleteDrag();
10725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window1_state->set_bounds_changed_by_user(true);
10745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window1->SetBounds(gfx::Rect(100, 0, 100, 100));
10755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2->Show();
10775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("0,0 100x100", window1->bounds().ToString());
10785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("300,0 100x100", window2->bounds().ToString());
10795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Window 1 should be restored to the user modified bounds.
10815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window2->Hide();
10825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("100,0 100x100", window1->bounds().ToString());
10835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
10845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a window from normal to minimize will repos the remaining.
1086a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, ToMinimizeRepositionsRemaining) {
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
108868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
108968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
109468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window2_state = wm::GetWindowState(window2.get());
109568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window2_state->set_window_position_managed(true);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
109868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Minimize();
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window2| should be centered now.
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->IsVisible());
1102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window2_state->IsNormalStateType());
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (desktop_area.width() - window2->bounds().width()) / 2) +
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",48 256x512", window2->bounds().ToString());
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Restore();
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be flush right and |window3| flush left.
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window1->bounds().width()) +
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",32 640x320", window1->bounds().ToString());
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,48 256x512", window2->bounds().ToString());
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that minimizing an initially maximized window will repos the remaining.
1116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, MaxToMinRepositionsRemaining) {
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
111868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
111968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
112368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window2_state = wm::GetWindowState(window2.get());
112468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window2_state->set_window_position_managed(true);
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Maximize();
112868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Minimize();
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window2| should be centered now.
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->IsVisible());
1132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window2_state->IsNormalStateType());
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (desktop_area.width() - window2->bounds().width()) / 2) +
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",48 256x512", window2->bounds().ToString());
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that nomral, maximize, minimizing will repos the remaining.
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, NormToMaxToMinRepositionsRemaining) {
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
114268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
114368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
114768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window2_state = wm::GetWindowState(window2.get());
114868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window2_state->set_window_position_managed(true);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 40, 256, 512));
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trigger the auto window placement function by showing (and hiding) it.
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be flush right and |window3| flush left.
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window1->bounds().width()) +
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",32 640x320", window1->bounds().ToString());
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
116168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Maximize();
116268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Minimize();
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window2| should be centered now.
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->IsVisible());
1166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window2_state->IsNormalStateType());
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (desktop_area.width() - window2->bounds().width()) / 2) +
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",40 256x512", window2->bounds().ToString());
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that nomral, maximize, normal will repos the remaining.
1173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, NormToMaxToNormRepositionsRemaining) {
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
117668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::WindowState* window1_state = wm::GetWindowState(window1.get());
117768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->set_window_position_managed(true);
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
118168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window2.get())->set_window_position_managed(true);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 40, 256, 512));
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trigger the auto window placement function by showing (and hiding) it.
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be flush right and |window3| flush left.
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window1->bounds().width()) +
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",32 640x320", window1->bounds().ToString());
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Maximize();
119568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window1_state->Restore();
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be flush right and |window2| flush left.
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window1->bounds().width()) +
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",32 640x320", window1->bounds().ToString());
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,40 256x512", window2->bounds().ToString());
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that animations are triggered.
1205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, AnimatedNormToMaxToNormRepositionsRemaining) {
12065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::ScopedAnimationDurationScaleMode test_duration_mode(
12075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0));
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Hide();
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->SetBounds(gfx::Rect(16, 32, 640, 320));
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect desktop_area = window1->parent()->bounds();
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1));
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Hide();
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->SetBounds(gfx::Rect(32, 48, 256, 512));
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
121668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window1.get())->set_window_position_managed(true);
121768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  wm::GetWindowState(window2.get())->set_window_position_managed(true);
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure nothing is animating.
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->layer()->GetAnimator()->StopAnimating();
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->layer()->GetAnimator()->StopAnimating();
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->Show();
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The second window should now animate.
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->layer()->GetAnimator()->StopAnimating();
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->Show();
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window1->layer()->GetAnimator()->StopAnimating();
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window2->layer()->GetAnimator()->StopAnimating();
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |window1| should be flush right and |window2| flush left.
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(base::IntToString(
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                desktop_area.width() - window1->bounds().width()) +
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ",32 640x320", window1->bounds().ToString());
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,48 256x512", window2->bounds().ToString());
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This tests simulates a browser and an app and verifies the ordering of the
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// windows and layers doesn't get out of sync as various operations occur. Its
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// really testing code in FocusController, but easier to simulate here. Just as
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with a real browser the browser here has a transient child window
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (corresponds to the status bubble).
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(WorkspaceControllerTest, VerifyLayerOrdering) {
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> browser(aura::test::CreateTestWindowWithDelegate(
12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 6, 7, 8), NULL));
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser->SetName("browser");
12501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(browser.get());
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser->Show();
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  wm::ActivateWindow(browser.get());
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |status_bubble| is made a transient child of |browser| and as a result
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // owned by |browser|.
12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::test::TestWindowDelegate* status_bubble_delegate =
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate();
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status_bubble_delegate->set_can_focus(false);
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Window* status_bubble =
12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      aura::test::CreateTestWindowWithDelegate(status_bubble_delegate,
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               ui::wm::WINDOW_TYPE_POPUP,
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               gfx::Rect(5, 6, 7, 8),
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               NULL);
1264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::AddTransientChild(browser.get(), status_bubble);
12651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(status_bubble);
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status_bubble->SetName("status_bubble");
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> app(aura::test::CreateTestWindowWithDelegate(
12695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 6, 7, 8), NULL));
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app->SetName("app");
12711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(app.get());
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* parent = browser->parent();
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app->Show();
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  wm::ActivateWindow(app.get());
12772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Minimize the app, focus should go the browser.
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(browser.get()));
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Minimize the browser (neither windows are focused).
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
12862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(wm::IsActiveWindow(browser.get()));
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(wm::IsActiveWindow(app.get()));
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Show the browser (which should restore it).
12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser->Show();
12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Activate the browser.
12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::wm::ActivateWindow(browser.get());
12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(browser.get()));
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Restore the app. This differs from above code for |browser| as internally
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the app code does this. Restoring this way or using Show() should not make
13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a difference.
13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
13032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Activate the app.
13062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::wm::ActivateWindow(app.get());
13072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(wm::IsActiveWindow(app.get()));
13082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetWindowNames(parent), GetLayerNames(parent));
13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
13122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used by DragMaximizedNonTrackedWindow to track how many times the window
1314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// hierarchy changes affecting the specified window.
13152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DragMaximizedNonTrackedWindowObserver
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public aura::WindowObserver {
13172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DragMaximizedNonTrackedWindowObserver(aura::Window* window)
1319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  : change_count_(0),
1320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    window_(window) {
13212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of times OnWindowHierarchyChanged() has been received.
13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void clear_change_count() { change_count_ = 0; }
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int change_count() const {
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return change_count_;
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // aura::WindowObserver overrides:
13303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Counts number of times a window is reparented. Ignores reparenting into and
13313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // from a docked container which is expected when a tab is dragged.
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWindowHierarchyChanged(
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const HierarchyChangeParams& params) OVERRIDE {
1334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (params.target != window_ ||
1335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        (params.old_parent->id() == kShellWindowId_DefaultContainer &&
13363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         params.new_parent->id() == kShellWindowId_DockedContainer) ||
13373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (params.old_parent->id() == kShellWindowId_DockedContainer &&
13383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         params.new_parent->id() == kShellWindowId_DefaultContainer)) {
13393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
13403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change_count_++;
13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int change_count_;
1346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window* window_;
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DragMaximizedNonTrackedWindowObserver);
13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that a new maximized window becomes visible after its activation
1354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// is requested, even though it does not become activated because a system
1355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// modal window is active.
1356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WorkspaceControllerTest, SwitchFromModal) {
1357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<Window> modal_window(CreateTestWindowUnparented());
1358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  modal_window->SetBounds(gfx::Rect(10, 11, 21, 22));
1359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
1360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(modal_window.get());
1361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  modal_window->Show();
1362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  wm::ActivateWindow(modal_window.get());
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<Window> maximized_window(CreateTestWindow());
1365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  maximized_window->SetProperty(
1366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  maximized_window->Show();
1368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  wm::ActivateWindow(maximized_window.get());
1369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(maximized_window->IsVisible());
1370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
13715e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
13735e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Subclass of WorkspaceControllerTest that runs tests with docked windows
1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// enabled and disabled.
1376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class WorkspaceControllerTestDragging : public WorkspaceControllerTest {
1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
1378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  WorkspaceControllerTestDragging() {}
1379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~WorkspaceControllerTestDragging() {}
1380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestDragging);
1383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
13845e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
13865e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that when dragging a window over the shelf overlap is detected
1388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// during and after the drag.
1389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(WorkspaceControllerTestDragging, DragWindowOverlapShelf) {
13905e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  aura::test::TestWindowDelegate delegate;
13915e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  delegate.set_window_component(HTCAPTION);
13925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate(
13935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL));
13941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(w1.get());
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
1397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Drag near the shelf.
14005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
14015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     gfx::Point());
1402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  generator.MoveMouseTo(10, 10);
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.PressLeftButton();
14045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 70);
14055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Shelf should not be in overlapped state.
14075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(GetWindowOverlapsShelf());
14085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  generator.MoveMouseTo(100, shelf->GetIdealBounds().y() - 20);
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Shelf should detect overlap. Overlap state stays after mouse is released.
1412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(GetWindowOverlapsShelf());
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generator.ReleaseLeftButton();
1414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(GetWindowOverlapsShelf());
14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verifies that when dragging a window autohidden shelf stays hidden during
14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and after the drag.
1419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(WorkspaceControllerTestDragging, DragWindowKeepsShelfAutohidden) {
14205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
14215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate.set_window_component(HTCAPTION);
14225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate(
14235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL));
14245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(w1.get());
14255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ShelfLayoutManager* shelf = shelf_layout_manager();
14275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
14285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
14295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Drag very little.
14315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
14325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     gfx::Point());
14335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  generator.MoveMouseTo(10, 10);
14345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  generator.PressLeftButton();
14355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  generator.MoveMouseTo(12, 12);
14365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Shelf should be hidden during and after the drag.
14385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
14395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  generator.ReleaseLeftButton();
14405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
14415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
14425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verifies that events are targeted properly just outside the window edges.
14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WorkspaceControllerTest, WindowEdgeHitTest) {
14455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::test::TestWindowDelegate d_first, d_second;
14465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> first(aura::test::CreateTestWindowWithDelegate(&d_first,
14475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      123, gfx::Rect(20, 10, 100, 50), NULL));
14485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(first.get());
14495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  first->Show();
14505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> second(aura::test::CreateTestWindowWithDelegate(&d_second,
14525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      234, gfx::Rect(30, 40, 40, 10), NULL));
14535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(second.get());
14545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  second->Show();
14555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTarget* root = first->GetRootWindow();
14575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTargeter* targeter = root->GetEventTargeter();
14585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The windows overlap, and |second| is on top of |first|. Events targeted
14605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // slightly outside the edges of the |second| window should still be targeted
14615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to |second| to allow resizing the windows easily.
14625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kNumPoints = 4;
14645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct {
14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* direction;
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Point location;
14675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } points[kNumPoints] = {
14685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "left", gfx::Point(28, 45) },  // outside the left edge.
14695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "top", gfx::Point(50, 38) },  // outside the top edge.
14705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "right", gfx::Point(72, 45) },  // outside the right edge.
14715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "bottom", gfx::Point(50, 52) },  // outside the bottom edge.
14725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Do two iterations, first without any transform on |second|, and the second
14745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // time after applying some transform on |second| so that it doesn't get
14755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // targeted.
14765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int times = 0; times < 2; ++times) {
14775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SCOPED_TRACE(times == 0 ? "Without transform" : "With transform");
14785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::Window* expected_target = times == 0 ? second.get() : first.get();
14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int i = 0; i < kNumPoints; ++i) {
14805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SCOPED_TRACE(points[i].direction);
14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::Point& location = points[i].location;
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
14835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           ui::EF_NONE);
14845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(expected_target, target);
14865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           ui::EventTimeForNow());
14895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      target = targeter->FindTargetForEvent(root, &touch);
14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(expected_target, target);
14915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
14925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Apply a transform on |second|. After the transform is applied, the window
14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // should no longer be targeted.
14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Transform transform;
14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    transform.Translate(70, 40);
14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    second->SetTransform(transform);
14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
14985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
14995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Verifies mouse event targeting just outside the window edges for panels.
15010529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(WorkspaceControllerTest, WindowEdgeMouseHitTestPanel) {
15025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
15035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> window(CreateTestPanel(&delegate,
15045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           gfx::Rect(20, 10, 100, 50)));
15055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTarget* root = window->GetRootWindow();
15065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTargeter* targeter = root->GetEventTargeter();
15075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Rect bounds = window->bounds();
15085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kNumPoints = 5;
15095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct {
15105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* direction;
15115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Point location;
15125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_target_hit;
15135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } points[kNumPoints] = {
15145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true },
15155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true },
15165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true },
15175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), true },
15185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false },
15195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
15205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < kNumPoints; ++i) {
15215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SCOPED_TRACE(points[i].direction);
15225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Point& location = points[i].location;
15235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
15245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         ui::EF_NONE);
15255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
15265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (points[i].is_target_hit)
15275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(window.get(), target);
15285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
15295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_NE(window.get(), target);
15300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
15310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
15325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Verifies touch event targeting just outside the window edges for panels.
15340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// The shelf is aligned to the bottom by default, and so touches just below
15350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// the bottom edge of the panel should not target the panel itself because
15360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// an AttachedPanelWindowTargeter is installed on the panel container.
15370529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(WorkspaceControllerTest, WindowEdgeTouchHitTestPanel) {
15380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  aura::test::TestWindowDelegate delegate;
15390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<Window> window(CreateTestPanel(&delegate,
15400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                            gfx::Rect(20, 10, 100, 50)));
15410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ui::EventTarget* root = window->GetRootWindow();
15420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ui::EventTargeter* targeter = root->GetEventTargeter();
15430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const gfx::Rect bounds = window->bounds();
15440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const int kNumPoints = 5;
15450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  struct {
15460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const char* direction;
15470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    gfx::Point location;
15480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    bool is_target_hit;
15490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } points[kNumPoints] = {
15500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { "left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true },
15510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { "top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true },
15520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { "right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true },
15530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { "bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), false },
15540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { "outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false },
15550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  };
15560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (int i = 0; i < kNumPoints; ++i) {
15570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SCOPED_TRACE(points[i].direction);
15580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const gfx::Point& location = points[i].location;
15595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
15605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         ui::EventTimeForNow());
15610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ui::EventTarget* target = targeter->FindTargetForEvent(root, &touch);
15625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (points[i].is_target_hit)
15635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(window.get(), target);
15645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
15655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_NE(window.get(), target);
15665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
15675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
15685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verifies events targeting just outside the window edges for docked windows.
15705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WorkspaceControllerTest, WindowEdgeHitTestDocked) {
15715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
15725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make window smaller than the minimum docked area so that the window edges
15735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // are exposed.
15745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate.set_maximum_size(gfx::Size(180, 200));
15755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Window> window(aura::test::CreateTestWindowWithDelegate(&delegate,
15765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      123, gfx::Rect(20, 10, 100, 50), NULL));
15775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParentWindowInPrimaryRootWindow(window.get());
15785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* docked_container = Shell::GetContainer(
1579c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      window->GetRootWindow(), kShellWindowId_DockedContainer);
15805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  docked_container->AddChild(window.get());
15815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window->Show();
15825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTarget* root = window->GetRootWindow();
15835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::EventTargeter* targeter = root->GetEventTargeter();
15845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Rect bounds = window->bounds();
15855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kNumPoints = 5;
15865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct {
15875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* direction;
15885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Point location;
15895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_target_hit;
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } points[kNumPoints] = {
15915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true },
15925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true },
15935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true },
15945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), true },
15955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false },
15965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
15975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < kNumPoints; ++i) {
15985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SCOPED_TRACE(points[i].direction);
15995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::Point& location = points[i].location;
16005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, ui::EF_NONE,
16015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         ui::EF_NONE);
16025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse);
16035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (points[i].is_target_hit)
16045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(window.get(), target);
16055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
16065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_NE(window.get(), target);
16075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, location, 0,
16095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         ui::EventTimeForNow());
16105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    target = targeter->FindTargetForEvent(root, &touch);
16115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (points[i].is_target_hit)
16125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(window.get(), target);
16135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
16145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_NE(window.get(), target);
16155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
16165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
16175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
1619