Home | History | Annotate | Download | only in dock
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ash/wm/dock/docked_window_resizer.h"
      6 
      7 #include "ash/ash_switches.h"
      8 #include "ash/launcher/launcher.h"
      9 #include "ash/root_window_controller.h"
     10 #include "ash/screen_ash.h"
     11 #include "ash/shelf/shelf_layout_manager.h"
     12 #include "ash/shelf/shelf_model.h"
     13 #include "ash/shelf/shelf_types.h"
     14 #include "ash/shelf/shelf_widget.h"
     15 #include "ash/shell.h"
     16 #include "ash/shell_window_ids.h"
     17 #include "ash/test/ash_test_base.h"
     18 #include "ash/test/cursor_manager_test_api.h"
     19 #include "ash/test/shell_test_api.h"
     20 #include "ash/test/test_shelf_delegate.h"
     21 #include "ash/wm/coordinate_conversion.h"
     22 #include "ash/wm/dock/docked_window_layout_manager.h"
     23 #include "ash/wm/drag_window_resizer.h"
     24 #include "ash/wm/panels/panel_layout_manager.h"
     25 #include "ash/wm/window_state.h"
     26 #include "ash/wm/window_util.h"
     27 #include "ash/wm/workspace/snap_sizer.h"
     28 #include "base/command_line.h"
     29 #include "ui/aura/client/aura_constants.h"
     30 #include "ui/aura/client/window_tree_client.h"
     31 #include "ui/aura/root_window.h"
     32 #include "ui/aura/test/test_window_delegate.h"
     33 #include "ui/base/hit_test.h"
     34 #include "ui/base/ui_base_types.h"
     35 #include "ui/views/widget/widget.h"
     36 
     37 namespace ash {
     38 namespace internal {
     39 
     40 class DockedWindowResizerTest
     41     : public test::AshTestBase,
     42       public testing::WithParamInterface<aura::client::WindowType> {
     43  public:
     44   DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {}
     45   virtual ~DockedWindowResizerTest() {}
     46 
     47   virtual void SetUp() OVERRIDE {
     48     CommandLine::ForCurrentProcess()->AppendSwitch(
     49         ash::switches::kAshEnableDockedWindows);
     50     AshTestBase::SetUp();
     51     UpdateDisplay("600x400");
     52     test::ShellTestApi test_api(Shell::GetInstance());
     53     model_ = test_api.shelf_model();
     54   }
     55 
     56   virtual void TearDown() OVERRIDE {
     57     AshTestBase::TearDown();
     58   }
     59 
     60  protected:
     61   enum DockedEdge {
     62     DOCKED_EDGE_NONE,
     63     DOCKED_EDGE_LEFT,
     64     DOCKED_EDGE_RIGHT,
     65   };
     66 
     67   int ideal_width() const { return DockedWindowLayoutManager::kIdealWidth; }
     68   int min_dock_gap() const { return DockedWindowLayoutManager::kMinDockGap; }
     69   int max_width() const { return DockedWindowLayoutManager::kMaxDockWidth; }
     70   int docked_width(const DockedWindowLayoutManager* layout_manager) const {
     71     return layout_manager->docked_width_;
     72   }
     73   int docked_alignment(const DockedWindowLayoutManager* layout_manager) const {
     74     return layout_manager->alignment_;
     75   }
     76   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
     77     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
     78         &delegate_,
     79         window_type_,
     80         0,
     81         bounds);
     82     if (window_type_ == aura::client::WINDOW_TYPE_PANEL) {
     83       test::TestShelfDelegate* shelf_delegate =
     84           test::TestShelfDelegate::instance();
     85       shelf_delegate->AddLauncherItem(window);
     86       PanelLayoutManager* manager =
     87           static_cast<PanelLayoutManager*>(
     88               Shell::GetContainer(window->GetRootWindow(),
     89                                   internal::kShellWindowId_PanelContainer)->
     90                   layout_manager());
     91       manager->Relayout();
     92     }
     93     return window;
     94   }
     95 
     96   aura::Window* CreateModalWindow(const gfx::Rect& bounds) {
     97     aura::Window* window = new aura::Window(&delegate_);
     98     window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
     99     window->SetType(aura::client::WINDOW_TYPE_NORMAL);
    100     window->Init(ui::LAYER_TEXTURED);
    101     window->Show();
    102 
    103     if (bounds.IsEmpty()) {
    104       ParentWindowInPrimaryRootWindow(window);
    105     } else {
    106       gfx::Display display =
    107           Shell::GetScreen()->GetDisplayMatching(bounds);
    108       aura::Window* root = ash::Shell::GetInstance()->display_controller()->
    109           GetRootWindowForDisplayId(display.id());
    110       gfx::Point origin = bounds.origin();
    111       wm::ConvertPointFromScreen(root, &origin);
    112       window->SetBounds(gfx::Rect(origin, bounds.size()));
    113       aura::client::ParentWindowWithContext(window, root, bounds);
    114     }
    115     return window;
    116   }
    117 
    118   static WindowResizer* CreateSomeWindowResizer(
    119       aura::Window* window,
    120       const gfx::Point& point_in_parent,
    121       int window_component) {
    122     return CreateWindowResizer(
    123         window,
    124         point_in_parent,
    125         window_component,
    126         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
    127   }
    128 
    129   void DragStart(aura::Window* window) {
    130     DragStartAtOffsetFromWindowOrigin(window, 0, 0);
    131   }
    132 
    133   void DragStartAtOffsetFromWindowOrigin(aura::Window* window,
    134                                          int dx, int dy) {
    135     initial_location_in_parent_ =
    136         window->bounds().origin() + gfx::Vector2d(dx, dy);
    137     resizer_.reset(CreateSomeWindowResizer(window,
    138                                            initial_location_in_parent_,
    139                                            HTCAPTION));
    140     ASSERT_TRUE(resizer_.get());
    141   }
    142 
    143   void ResizeStartAtOffsetFromWindowOrigin(aura::Window* window,
    144                                            int dx, int dy,
    145                                            int window_component) {
    146     initial_location_in_parent_ =
    147         window->bounds().origin() + gfx::Vector2d(dx, dy);
    148     resizer_.reset(CreateSomeWindowResizer(window,
    149                                            initial_location_in_parent_,
    150                                            window_component));
    151     ASSERT_TRUE(resizer_.get());
    152   }
    153 
    154   void DragMove(int dx, int dy) {
    155     resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0);
    156   }
    157 
    158   void DragEnd() {
    159     resizer_->CompleteDrag(0);
    160     resizer_.reset();
    161   }
    162 
    163   void DragRevert() {
    164     resizer_->RevertDrag();
    165     resizer_.reset();
    166   }
    167 
    168   // Panels are parented by panel container during drags.
    169   // All other windows that are tested here are parented by dock container
    170   // during drags.
    171   int CorrectContainerIdDuringDrag() {
    172     if (window_type_ == aura::client::WINDOW_TYPE_PANEL)
    173       return internal::kShellWindowId_PanelContainer;
    174     return internal::kShellWindowId_DockedContainer;
    175   }
    176 
    177   // Test dragging the window vertically (to detach if it is a panel) and then
    178   // horizontally to the edge with an added offset from the edge of |dx|.
    179   void DragRelativeToEdge(DockedEdge edge,
    180                           aura::Window* window,
    181                           int dx) {
    182     DragVerticallyAndRelativeToEdge(
    183         edge,
    184         window,
    185         dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20,
    186         25, 5);
    187   }
    188 
    189   void DragToVerticalPositionAndToEdge(DockedEdge edge,
    190                                        aura::Window* window,
    191                                        int y) {
    192     DragToVerticalPositionRelativeToEdge(edge, window, 0, y);
    193   }
    194 
    195   void DragToVerticalPositionRelativeToEdge(DockedEdge edge,
    196                                             aura::Window* window,
    197                                             int dx,
    198                                             int y) {
    199     gfx::Rect initial_bounds = window->GetBoundsInScreen();
    200     DragVerticallyAndRelativeToEdge(edge,
    201                                     window,
    202                                     dx, y - initial_bounds.y(),
    203                                     25, 5);
    204   }
    205 
    206   // Detach if our window is a panel, then drag it vertically by |dy| and
    207   // horizontally to the edge with an added offset from the edge of |dx|.
    208   void DragVerticallyAndRelativeToEdge(DockedEdge edge,
    209                                        aura::Window* window,
    210                                        int dx, int dy,
    211                                        int grab_x, int grab_y) {
    212     gfx::Rect initial_bounds = window->GetBoundsInScreen();
    213     // avoid snap by clicking away from the border
    214     ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(window,
    215                                                               grab_x, grab_y));
    216 
    217     gfx::Rect work_area =
    218         Shell::GetScreen()->GetDisplayNearestWindow(window).work_area();
    219     gfx::Point initial_location_in_screen = initial_location_in_parent_;
    220     wm::ConvertPointToScreen(window->parent(), &initial_location_in_screen);
    221     // Drag the window left or right to the edge (or almost to it).
    222     if (edge == DOCKED_EDGE_LEFT)
    223       dx += work_area.x() - initial_location_in_screen.x();
    224     else if (edge == DOCKED_EDGE_RIGHT)
    225       dx += work_area.right() - 1 - initial_location_in_screen.x();
    226     DragMove(dx, dy);
    227     EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
    228     // Release the mouse and the panel should be attached to the dock.
    229     DragEnd();
    230 
    231     // x-coordinate can get adjusted by snapping or sticking.
    232     // y-coordinate could be changed by possible automatic layout if docked.
    233     if (window->parent()->id() != internal::kShellWindowId_DockedContainer &&
    234         !wm::GetWindowState(window)->HasRestoreBounds()) {
    235       EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
    236     }
    237   }
    238 
    239   bool test_panels() const {
    240     return window_type_ == aura::client::WINDOW_TYPE_PANEL;
    241   }
    242 
    243   const gfx::Point& initial_location_in_parent() const {
    244     return initial_location_in_parent_;
    245   }
    246 
    247  private:
    248   scoped_ptr<WindowResizer> resizer_;
    249   ShelfModel* model_;
    250   aura::client::WindowType window_type_;
    251   aura::test::TestWindowDelegate delegate_;
    252 
    253   // Location at start of the drag in |window->parent()|'s coordinates.
    254   gfx::Point initial_location_in_parent_;
    255 
    256   DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest);
    257 };
    258 
    259 // Verifies a window can be dragged and attached to the dock.
    260 TEST_P(DockedWindowResizerTest, AttachRightPrecise) {
    261   if (!SupportsHostWindowResize())
    262     return;
    263 
    264   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    265   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    266 
    267   // The window should be docked at the right edge.
    268   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    269             window->GetBoundsInScreen().right());
    270   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    271 }
    272 
    273 // Verifies a window can be dragged and attached to the dock
    274 // even if pointer overshoots the screen edge by a few pixels (sticky edge)
    275 TEST_P(DockedWindowResizerTest, AttachRightOvershoot) {
    276   if (!SupportsHostWindowResize())
    277     return;
    278 
    279   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    280   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4);
    281 
    282   // The window should be docked at the right edge.
    283   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    284             window->GetBoundsInScreen().right());
    285   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    286 }
    287 
    288 // Verifies a window can be dragged and then if a pointer is not quite reaching
    289 // the screen edge the window does not get docked and stays in the desktop.
    290 TEST_P(DockedWindowResizerTest, AttachRightUndershoot) {
    291   if (!SupportsHostWindowResize())
    292     return;
    293 
    294   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    295   // Grabbing at 70px ensures that at least 30% of the window is in screen,
    296   // otherwise the window would be adjusted in
    297   // WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded.
    298   const int kGrabOffsetX = 70;
    299   const int kUndershootBy = 1;
    300   DragVerticallyAndRelativeToEdge(DOCKED_EDGE_RIGHT,
    301                                   window.get(),
    302                                   -kUndershootBy, test_panels() ? -100 : 20,
    303                                   kGrabOffsetX, 5);
    304 
    305   // The window right should be past the screen edge but not docked.
    306   // Initial touch point is 70px to the right which helps to find where the edge
    307   // should be.
    308   EXPECT_EQ(window->GetRootWindow()->bounds().right() +
    309             window->bounds().width() - kGrabOffsetX - kUndershootBy - 1,
    310             window->GetBoundsInScreen().right());
    311   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    312             window->parent()->id());
    313 }
    314 
    315 // Verifies a window can be dragged and attached to the dock.
    316 TEST_P(DockedWindowResizerTest, AttachLeftPrecise) {
    317   if (!SupportsHostWindowResize())
    318     return;
    319 
    320   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    321   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0);
    322 
    323   // The window should be docked at the left edge.
    324   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    325             window->GetBoundsInScreen().x());
    326   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    327 }
    328 
    329 // Verifies a window can be dragged and attached to the dock
    330 // even if pointer overshoots the screen edge by a few pixels (sticky edge)
    331 TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) {
    332   if (!SupportsHostWindowResize())
    333     return;
    334 
    335   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    336   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4);
    337 
    338   // The window should be docked at the left edge.
    339   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    340             window->GetBoundsInScreen().x());
    341   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    342 }
    343 
    344 // Verifies a window can be dragged and then if a pointer is not quite reaching
    345 // the screen edge the window does not get docked and stays in the desktop.
    346 TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) {
    347   if (!SupportsHostWindowResize())
    348     return;
    349 
    350   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    351   gfx::Rect initial_bounds(window->bounds());
    352   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1);
    353 
    354   // The window should be crossing the screen edge but not docked.
    355   int expected_x = initial_bounds.x() - initial_location_in_parent().x() + 1;
    356   EXPECT_EQ(expected_x, window->GetBoundsInScreen().x());
    357   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    358             window->parent()->id());
    359 }
    360 
    361 // Dock on the right side, change shelf alignment, check that windows move to
    362 // the opposite side.
    363 TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) {
    364   if (!SupportsHostWindowResize())
    365     return;
    366 
    367   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    368   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    369 
    370   // The window should be docked at the right edge.
    371   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    372             window->GetBoundsInScreen().right());
    373   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    374 
    375   // set launcher shelf to be aligned on the right
    376   ash::Shell* shell = ash::Shell::GetInstance();
    377   shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
    378                            shell->GetPrimaryRootWindow());
    379   // The window should have moved and get attached to the left dock.
    380   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    381             window->GetBoundsInScreen().x());
    382   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    383 
    384   // set launcher shelf to be aligned on the left
    385   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
    386                            shell->GetPrimaryRootWindow());
    387   // The window should have moved and get attached to the right edge.
    388   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    389             window->GetBoundsInScreen().right());
    390   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    391 
    392   // set launcher shelf to be aligned at the bottom
    393   shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM,
    394                            shell->GetPrimaryRootWindow());
    395   // The window should stay in the right edge.
    396   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    397             window->GetBoundsInScreen().right());
    398   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    399 }
    400 
    401 // Dock on the right side, try to undock, then drag more to really undock
    402 TEST_P(DockedWindowResizerTest, AttachTryDetach) {
    403   if (!SupportsHostWindowResize())
    404     return;
    405 
    406   scoped_ptr<aura::Window> window(CreateTestWindow(
    407       gfx::Rect(0, 0, ideal_width() + 10, 201)));
    408   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    409 
    410   // The window should be docked at the right edge.
    411   // Its width should shrink to ideal width.
    412   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    413             window->GetBoundsInScreen().right());
    414   EXPECT_EQ(ideal_width(), window->GetBoundsInScreen().width());
    415   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    416 
    417   // Try to detach by dragging left less than kSnapToDockDistance.
    418   // The window should stay docked.
    419   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
    420       window.get(), 10, 0));
    421   DragMove(-4, -10);
    422   // Release the mouse and the window should be still attached to the dock.
    423   DragEnd();
    424 
    425   // The window should be still attached to the right edge.
    426   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    427             window->GetBoundsInScreen().right());
    428   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    429 
    430   // Try to detach by dragging left by kSnapToDockDistance or more.
    431   // The window should get undocked.
    432   const int left_edge = window->bounds().x();
    433   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    434   DragMove(-32, -10);
    435   // Release the mouse and the window should be no longer attached to the dock.
    436   DragEnd();
    437 
    438   // The window should be floating on the desktop again and moved to the left.
    439   EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x());
    440   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    441             window->parent()->id());
    442 }
    443 
    444 // Minimize a docked window, then restore it and check that it is still docked.
    445 TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) {
    446   if (!SupportsHostWindowResize())
    447     return;
    448 
    449   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    450   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    451 
    452   // The window should be docked at the right edge.
    453   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    454             window->GetBoundsInScreen().right());
    455   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    456 
    457   wm::WindowState* window_state = wm::GetWindowState(window.get());
    458   // Minimize the window, it should be hidden.
    459   window_state->Minimize();
    460   RunAllPendingInMessageLoop();
    461   EXPECT_FALSE(window->IsVisible());
    462   EXPECT_TRUE(window_state->IsMinimized());
    463   // Restore the window; window should be visible.
    464   window_state->Restore();
    465   RunAllPendingInMessageLoop();
    466   EXPECT_TRUE(window->IsVisible());
    467   EXPECT_TRUE(window_state->IsNormalShowState());
    468 }
    469 
    470 // Maximize a docked window and check that it is maximized and no longer docked.
    471 TEST_P(DockedWindowResizerTest, AttachMaximize) {
    472   if (!SupportsHostWindowResize())
    473     return;
    474 
    475   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    476   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    477 
    478   // The window should be docked at the right edge.
    479   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    480             window->GetBoundsInScreen().right());
    481   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    482 
    483   wm::WindowState* window_state = wm::GetWindowState(window.get());
    484   // Maximize the window, it should get undocked and maximized in a desktop.
    485   window_state->Maximize();
    486   RunAllPendingInMessageLoop();
    487   EXPECT_TRUE(window->IsVisible());
    488   EXPECT_TRUE(window_state->IsMaximized());
    489   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
    490 }
    491 
    492 // Dock two windows, undock one, check that the other one is still docked.
    493 TEST_P(DockedWindowResizerTest, AttachTwoWindows) {
    494   if (!SupportsHostWindowResize())
    495     return;
    496 
    497   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    498   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    499   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    500   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50);
    501 
    502   // Both windows should be docked at the right edge.
    503   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    504             w1->GetBoundsInScreen().right());
    505   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    506 
    507   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    508             w2->GetBoundsInScreen().right());
    509   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    510 
    511   // Detach by dragging left (should get undocked).
    512   const int left_edge = w2->bounds().x();
    513   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    514   // Drag up as well to avoid attaching panels to launcher shelf.
    515   DragMove(-32, -100);
    516   // Release the mouse and the window should be no longer attached to the edge.
    517   DragEnd();
    518 
    519   // The first window should be still docked.
    520   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    521             w1->GetBoundsInScreen().right());
    522   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    523 
    524   // The window should be floating on the desktop again and moved to the left.
    525   EXPECT_EQ(left_edge - 32, w2->GetBoundsInScreen().x());
    526   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    527             w2->parent()->id());
    528 }
    529 
    530 // Create two windows, dock one and change shelf to auto-hide.
    531 TEST_P(DockedWindowResizerTest, AttachOneAutoHideShelf) {
    532   if (!SupportsHostWindowResize())
    533     return;
    534 
    535   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    536   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    537 
    538   // w1 should be docked at the right edge.
    539   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    540             w1->GetBoundsInScreen().right());
    541   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    542 
    543   scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegateAndType(
    544       NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20)));
    545   wm::GetWindowState(w2.get())->Maximize();
    546   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    547   EXPECT_TRUE(wm::GetWindowState(w2.get())->IsMaximized());
    548 
    549   gfx::Rect work_area =
    550       Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area();
    551   DockedWindowLayoutManager* manager =
    552       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    553 
    554   // Docked window should be centered vertically in the work area.
    555   EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y());
    556   // Docked background should extend to the bottom of work area.
    557   EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom());
    558 
    559   // set launcher shelf to be aligned on the right
    560   ash::Shell* shell = ash::Shell::GetInstance();
    561   shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS,
    562                                   shell->GetPrimaryRootWindow());
    563   work_area =
    564         Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area();
    565   // Docked window should be centered vertically in the work area.
    566   EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y());
    567   // Docked background should extend to the bottom of work area.
    568   EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom());
    569 }
    570 
    571 // Dock one window, try to dock another window on the opposite side (should not
    572 // dock).
    573 TEST_P(DockedWindowResizerTest, AttachOnTwoSides) {
    574   if (!SupportsHostWindowResize())
    575     return;
    576 
    577   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    578   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    579   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    580   gfx::Rect initial_bounds(w2->bounds());
    581   DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50);
    582 
    583   // The first window should be docked at the right edge.
    584   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    585             w1->GetBoundsInScreen().right());
    586   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    587 
    588   // The second window should be near the left edge but not snapped.
    589   // Normal window will get side-maximized while panels will not.
    590   int expected_x = test_panels() ?
    591       (initial_bounds.x() - initial_location_in_parent().x()) : 0;
    592   EXPECT_EQ(expected_x, w2->GetBoundsInScreen().x());
    593   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    594 }
    595 
    596 // Tests that reverting a drag restores docked state if a window was docked.
    597 TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) {
    598   if (!SupportsHostWindowResize())
    599     return;
    600 
    601   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    602   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    603 
    604   // The window should be docked at the right edge.
    605   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    606             window->GetBoundsInScreen().right());
    607   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    608 
    609   // Drag the window out but revert the drag
    610   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    611   DragMove(-50, 0);
    612   DragRevert();
    613   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    614 
    615   // Detach window.
    616   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    617   DragMove(-50, 0);
    618   DragEnd();
    619   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    620             window->parent()->id());
    621 }
    622 
    623 // Tests that reverting drag restores undocked state if a window was not docked.
    624 TEST_P(DockedWindowResizerTest, RevertDockedDragRevertsAttachment) {
    625   if (!SupportsHostWindowResize())
    626     return;
    627   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    628   int previous_container_id = window->parent()->id();
    629   // Drag the window out but revert the drag
    630   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    631   DragMove(-50 - window->bounds().x(), 50 - window->bounds().y());
    632   EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
    633   DragRevert();
    634   EXPECT_EQ(previous_container_id, window->parent()->id());
    635 }
    636 
    637 // Move a docked window to the second display
    638 TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
    639   if (!SupportsMultipleDisplays())
    640     return;
    641 
    642   UpdateDisplay("800x800,800x800");
    643   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    644   EXPECT_EQ(2, static_cast<int>(root_windows.size()));
    645   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    646   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    647   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    648 
    649   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    650   // The window should be docked at the right edge.
    651   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    652             window->GetBoundsInScreen().right());
    653   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    654 
    655   // Try dragging to the right - enough to get it peeking at the other screen
    656   // but not enough to land in the other screen.
    657   // The window should stay on the left screen.
    658   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    659   DragMove(100, 0);
    660   EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
    661   DragEnd();
    662   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    663             window->GetBoundsInScreen().right());
    664   EXPECT_EQ(internal::kShellWindowId_DockedContainer,
    665             window->parent()->id());
    666   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    667 
    668   // Undock and move to the right - enough to get the mouse pointer past the
    669   // edge of the screen and into the second screen. The window should now be
    670   // in the second screen and not docked.
    671   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
    672       window.get(),
    673       window->bounds().width()/2 + 10,
    674       0));
    675   DragMove(window->bounds().width()/2 - 5, 0);
    676   EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
    677   DragEnd();
    678   EXPECT_NE(window->GetRootWindow()->bounds().right(),
    679             window->GetBoundsInScreen().right());
    680   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    681             window->parent()->id());
    682   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    683 
    684   // Keep dragging it to the right until its left edge touches the screen edge.
    685   // The window should now be in the second screen and not docked.
    686   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
    687       window.get(),
    688       window->bounds().width()/2 + 10,
    689       0));
    690   DragMove(window->GetRootWindow()->GetBoundsInScreen().x() -
    691            window->GetBoundsInScreen().x(),
    692            0);
    693   EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
    694   DragEnd();
    695   EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
    696             window->GetBoundsInScreen().x());
    697   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
    698   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    699 }
    700 
    701 // Dock two windows, undock one.
    702 // Test the docked windows area size and default container resizing.
    703 TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) {
    704   if (!SupportsHostWindowResize())
    705     return;
    706   UpdateDisplay("600x600");
    707 
    708   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    709   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    710   // Work area should cover the whole screen.
    711   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    712             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    713 
    714   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    715   // A window should be docked at the right edge.
    716   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    717             w1->GetBoundsInScreen().right());
    718   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    719   DockedWindowLayoutManager* manager =
    720       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    721   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    722   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    723 
    724   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
    725   // Both windows should now be docked at the right edge.
    726   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    727             w2->GetBoundsInScreen().right());
    728   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    729   // Dock width should be set to a wider window.
    730   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    731   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
    732             docked_width(manager));
    733 
    734   // Try to detach by dragging left a bit (should not get undocked).
    735   // This would normally detach a single docked window but since we have another
    736   // window and the mouse pointer does not leave the dock area the window
    737   // should stay docked.
    738   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 60, 0));
    739   // Drag up as well as left to avoid attaching panels to launcher shelf.
    740   DragMove(-40, -40);
    741   // Release the mouse and the window should be still attached to the edge.
    742   DragEnd();
    743 
    744   // The first window should be still docked.
    745   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    746             w1->GetBoundsInScreen().right());
    747   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    748 
    749   // The second window should be still docked.
    750   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    751             w2->GetBoundsInScreen().right());
    752   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    753 
    754   // Detach by dragging left more (should get undocked).
    755   const int left_edge = w2->bounds().x();
    756   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
    757       w2.get(),
    758       w2->bounds().width()/2 + 10,
    759       0));
    760   // Drag up as well to avoid attaching panels to launcher shelf.
    761   const int drag_x = -(w2->bounds().width()/2 + 20);
    762   DragMove(drag_x, -100);
    763   // Release the mouse and the window should be no longer attached to the edge.
    764   DragEnd();
    765 
    766   // The second window should be floating on the desktop again.
    767   EXPECT_EQ(left_edge + drag_x, w2->bounds().x());
    768   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    769   // Dock width should be set to remaining single docked window.
    770   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    771   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    772   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    773 }
    774 
    775 // Dock one of the windows. Maximize other testing desktop resizing.
    776 TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) {
    777   if (!SupportsHostWindowResize())
    778     return;
    779 
    780   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    781   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    782   // Work area should cover the whole screen.
    783   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    784             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    785 
    786   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    787   // A window should be docked at the right edge.
    788   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    789             w1->GetBoundsInScreen().right());
    790   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    791   DockedWindowLayoutManager* manager =
    792       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    793   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    794   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    795 
    796   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 25, 5));
    797   DragMove(w2->GetRootWindow()->bounds().right()
    798            -w2->bounds().width()
    799            -(w2->bounds().width()/2 + 20)
    800            -w2->bounds().x(),
    801            50 - w2->bounds().y());
    802   DragEnd();
    803   // The first window should be still docked.
    804   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    805             w1->GetBoundsInScreen().right());
    806   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    807 
    808   // The second window should be floating on the desktop.
    809   EXPECT_EQ(w2->GetRootWindow()->bounds().right() -
    810             (w2->bounds().width()/2 + 20),
    811             w2->GetBoundsInScreen().right());
    812   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    813   // Dock width should be set to remaining single docked window.
    814   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    815   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    816   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    817   // Desktop work area should now shrink.
    818   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    819             docked_width(manager) - min_dock_gap(),
    820             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    821 
    822   // Maximize the second window - Maximized area should be shrunk.
    823   const gfx::Rect restored_bounds = w2->bounds();
    824   wm::WindowState* w2_state = wm::GetWindowState(w2.get());
    825   w2_state->Maximize();
    826   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    827             docked_width(manager) - min_dock_gap(),
    828             w2->bounds().width());
    829 
    830   // Detach the first window (this should require very little drag).
    831   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
    832   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    833   DragMove(-35, 10);
    834   // Alignment is set to "NONE" when drag starts.
    835   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
    836   // Release the mouse and the window should be no longer attached to the edge.
    837   DragEnd();
    838   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
    839   // Dock should get shrunk and desktop should get expanded.
    840   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
    841   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    842   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
    843   EXPECT_EQ(0, docked_width(manager));
    844   // The second window should now get resized and take up the whole screen.
    845   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    846             w2->bounds().width());
    847 
    848   // Dock the first window to the left edge.
    849   // Click at an offset from origin to prevent snapping.
    850   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w1.get(), 10, 0));
    851   // Drag left to get pointer touching the screen edge.
    852   DragMove(-w1->bounds().x() - 10, 0);
    853   // Alignment set to "NONE" during the drag of the window when none are docked.
    854   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
    855   // Release the mouse and the window should be now attached to the edge.
    856   DragEnd();
    857   // Dock should get expanded and desktop should get shrunk.
    858   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    859   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    860   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    861   // Second window should still be in the desktop.
    862   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    863   // Maximized window should be shrunk.
    864   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    865             docked_width(manager) - min_dock_gap(),
    866             w2->bounds().width());
    867 
    868   // Unmaximize the second window.
    869   w2_state->Restore();
    870   // Its bounds should get restored.
    871   EXPECT_EQ(restored_bounds, w2->bounds());
    872 }
    873 
    874 // Dock one window. Test the sticky behavior near screen or desktop edge.
    875 TEST_P(DockedWindowResizerTest, AttachOneTestSticky) {
    876   if (!SupportsHostWindowResize())
    877     return;
    878 
    879   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    880   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    881   // Work area should cover the whole screen.
    882   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    883             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    884 
    885   DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20);
    886   // A window should be docked at the left edge.
    887   EXPECT_EQ(w1->GetRootWindow()->bounds().x(),
    888             w1->GetBoundsInScreen().x());
    889   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    890   DockedWindowLayoutManager* manager =
    891       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    892   // The first window should be docked.
    893   EXPECT_EQ(w1->GetRootWindow()->bounds().x(),
    894             w1->GetBoundsInScreen().x());
    895   // Dock width should be set to that of a single docked window.
    896   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    897   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    898   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    899 
    900   // Position second window in the desktop 20px to the right of the docked w1.
    901   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT,
    902                                        w2.get(),
    903                                        20 + 25 -
    904                                        min_dock_gap(),
    905                                        50);
    906   // The second window should be floating on the desktop.
    907   EXPECT_EQ(w2->GetRootWindow()->bounds().x() + (w1->bounds().right() + 20),
    908             w2->GetBoundsInScreen().x());
    909   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    910   // Dock width should be set to that of a single docked window.
    911   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    912   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    913   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    914 
    915   // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock.
    916   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 10, 0));
    917   DragMove(1 + docked_width(manager) - w2->bounds().x(), 0);
    918   // Alignment set to "LEFT" during the drag because dock has a window in it.
    919   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    920   // Release the mouse and the window should not be attached to the edge.
    921   DragEnd();
    922   // Dock should still have only one window in it.
    923   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    924   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    925   // The second window should still be in the desktop.
    926   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    927   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    928 
    929   // Drag w2 by a bit more - it should resist the drag (stuck edges)
    930   int start_x = w2->bounds().x();
    931   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 100, 5));
    932   DragMove(-2, 0);
    933   // Window should not actually move.
    934   EXPECT_EQ(start_x, w2->bounds().x());
    935   // Alignment set to "LEFT" during the drag because dock has a window in it.
    936   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    937   // Release the mouse and the window should not be attached to the edge.
    938   DragEnd();
    939   // Window should be still where it was before the last drag started.
    940   EXPECT_EQ(start_x, w2->bounds().x());
    941   // Dock should still have only one window in it
    942   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    943   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    944   // The second window should still be in the desktop
    945   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    946   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    947 
    948   // Drag w2 by more than the stuck threshold and drop it into the dock.
    949   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    950   DragMove(-100, 0);
    951   // Window should actually move.
    952   EXPECT_NE(start_x, w2->bounds().x());
    953   // Alignment set to "LEFT" during the drag because dock has a window in it.
    954   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    955   // Release the mouse and the window should be attached to the edge.
    956   DragEnd();
    957   // Both windows are docked now.
    958   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    959   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    960   // Dock should get expanded and desktop should get shrunk.
    961   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
    962   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
    963             docked_width(manager));
    964   // Desktop work area should now shrink by dock width.
    965   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    966             docked_width(manager) - min_dock_gap(),
    967             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    968 }
    969 
    970 // Dock two windows, resize one.
    971 // Test the docked windows area size and remaining desktop resizing.
    972 TEST_P(DockedWindowResizerTest, ResizeOneOfTwoWindows) {
    973   if (!SupportsHostWindowResize())
    974     return;
    975 
    976   // Wider display to start since panels are limited to half the display width.
    977   UpdateDisplay("1000x600");
    978   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    979   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    980   // Work area should cover the whole screen.
    981   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    982             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    983 
    984   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    985   // A window should be docked at the right edge.
    986   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    987             w1->GetBoundsInScreen().right());
    988   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    989   DockedWindowLayoutManager* manager =
    990       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    991   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
    992   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
    993 
    994   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
    995   // Both windows should now be docked at the right edge.
    996   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    997             w2->GetBoundsInScreen().right());
    998   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    999   // Dock width should be set to a wider window.
   1000   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1001   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
   1002             docked_width(manager));
   1003 
   1004   // Resize the first window left by a bit and test that the dock expands.
   1005   int previous_width = w1->bounds().width();
   1006   const int kResizeSpan1 = 30;
   1007   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1008                                                               0, 20,
   1009                                                               HTLEFT));
   1010   DragMove(-kResizeSpan1, 0);
   1011   // Alignment set to "RIGHT" during the drag because dock has a window in it.
   1012   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1013   // Release the mouse and the window should be attached to the edge.
   1014   DragEnd();
   1015   // Dock should still have both windows in it.
   1016   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1017   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1018   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1019   // w1 is now wider than before. The dock should expand and be as wide as w1.
   1020   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
   1021   // Both windows should get resized since they both don't have min/max size.
   1022   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1023   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1024   // Desktop work area should shrink.
   1025   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
   1026             docked_width(manager) - min_dock_gap(),
   1027             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
   1028 
   1029   // Resize the first window left by more than the dock maximum width.
   1030   // This should cause the window width to be restricted by maximum dock width.
   1031   previous_width = w1->bounds().width();
   1032   const int kResizeSpan2 = 250;
   1033   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1034                                                               0, 20,
   1035                                                               HTLEFT));
   1036   DragMove(-kResizeSpan2, 0);
   1037   // Alignment set to "RIGHT" during the drag because dock has a window in it.
   1038   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1039   // Release the mouse and the window should be attached to the edge.
   1040   DragEnd();
   1041   // Dock should still have both windows in it.
   1042   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1043   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1044   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1045   // w1 is now as wide as the maximum dock width and the dock should get
   1046   // resized to the maximum width.
   1047   EXPECT_EQ(max_width(), w1->bounds().width());
   1048   // Both windows should get resized since they both don't have min/max size.
   1049   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1050   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1051   // Desktop work area should shrink.
   1052   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
   1053             docked_width(manager) - min_dock_gap(),
   1054             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
   1055 
   1056   // Resize the first window right to get it completely inside the docked area.
   1057   previous_width = w1->bounds().width();
   1058   const int kResizeSpan3 = 100;
   1059   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1060                                                               0, 20,
   1061                                                               HTLEFT));
   1062   DragMove(kResizeSpan3, 0);
   1063   // Alignment set to "RIGHT" during the drag because dock has a window in it.
   1064   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1065   // Release the mouse and the window should be docked.
   1066   DragEnd();
   1067   // Dock should still have both windows in it.
   1068   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1069   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1070   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1071   // w1 should be narrower than before by the length of the drag.
   1072   EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width());
   1073   // Both windows should get resized since they both don't have min/max size.
   1074   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1075   // The dock should be as wide as w1 or w2.
   1076   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1077   // Desktop work area should shrink.
   1078   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
   1079             docked_width(manager) - min_dock_gap(),
   1080             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
   1081 
   1082   // Resize the first window left to be overhang again.
   1083   previous_width = w1->bounds().width();
   1084   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1085                                                               0, 20,
   1086                                                               HTLEFT));
   1087   DragMove(-kResizeSpan3, 0);
   1088   DragEnd();
   1089   EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width());
   1090   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1091   // Docked area should be as wide as possible (maximum) and same as w1.
   1092   EXPECT_EQ(max_width(), docked_width(manager));
   1093   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1094 
   1095   // Undock the first window. Docked area should shrink to its ideal size.
   1096   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
   1097   // Drag up as well to avoid attaching panels to launcher shelf.
   1098   DragMove(-(400 - 210), -100);
   1099   // Alignment set to "RIGHT" since we have another window docked.
   1100   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1101   // Release the mouse and the window should be no longer attached to the edge.
   1102   DragEnd();
   1103   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
   1104   // Dock should be as wide as w2 (and same as ideal width).
   1105   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1106   EXPECT_EQ(ideal_width(), docked_width(manager));
   1107   EXPECT_EQ(w2->bounds().width(), docked_width(manager));
   1108   // The second window should be still docked.
   1109   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1110   // Desktop work area should be inset.
   1111   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width() -
   1112             docked_width(manager) - min_dock_gap(),
   1113             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width());
   1114 }
   1115 
   1116 // Dock a window, resize it and test that undocking it preserves the width.
   1117 TEST_P(DockedWindowResizerTest, ResizingKeepsWidth) {
   1118   if (!SupportsHostWindowResize())
   1119     return;
   1120 
   1121   // Wider display to start since panels are limited to half the display width.
   1122   UpdateDisplay("1000x600");
   1123   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1124 
   1125   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1126   // A window should be docked at the right edge.
   1127   EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
   1128             w1->GetBoundsInScreen().right());
   1129   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1130   DockedWindowLayoutManager* manager =
   1131       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
   1132   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1133   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1134 
   1135   // Resize the window left by a bit and test that the dock expands.
   1136   int previous_width = w1->bounds().width();
   1137   const int kResizeSpan1 = 30;
   1138   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1139                                                               0, 20,
   1140                                                               HTLEFT));
   1141   DragMove(-kResizeSpan1, 0);
   1142   // Alignment set to "RIGHT" during the drag because the only docked window
   1143   // is being dragged.
   1144   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
   1145   // Release the mouse and the window should be attached to the edge.
   1146   DragEnd();
   1147   // A window should get docked.
   1148   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1149   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1150   // w1 is now wider and the dock should expand to be as wide as w1.
   1151   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
   1152   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1153 
   1154   // Undock by dragging almost to the left edge.
   1155   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20);
   1156   // Width should be preserved.
   1157   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
   1158   // Height should be restored to what it was originally.
   1159   EXPECT_EQ(201, w1->bounds().height());
   1160 
   1161   // Dock again.
   1162   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1163   // Width should be reset to initial ideal width (25px).
   1164   EXPECT_EQ(ideal_width(), w1->bounds().width());
   1165 
   1166   // Undock again by dragging left.
   1167   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20);
   1168   // Width should be reset to what it was last time the window was not docked.
   1169   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
   1170   // Height should be restored to what it was originally.
   1171   EXPECT_EQ(201, w1->bounds().height());
   1172 }
   1173 
   1174 // Dock two windows, resize one. Test the docked windows area size.
   1175 TEST_P(DockedWindowResizerTest, ResizeTwoWindows) {
   1176   if (!SupportsHostWindowResize())
   1177     return;
   1178 
   1179   // Wider display to start since panels are limited to half the display width.
   1180   UpdateDisplay("1000x600");
   1181   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1182   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
   1183 
   1184   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1185   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
   1186   // Both windows should now be docked at the right edge.
   1187   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1188   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1189   // Dock width should be set to ideal width.
   1190   DockedWindowLayoutManager* manager =
   1191       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
   1192   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1193   EXPECT_EQ(ideal_width(), docked_width(manager));
   1194 
   1195   // Resize the first window left by a bit and test that the dock expands.
   1196   int previous_width = w1->bounds().width();
   1197   const int kResizeSpan1 = 30;
   1198   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1199                                                               0, 20,
   1200                                                               HTLEFT));
   1201   DragMove(-kResizeSpan1, 0);
   1202   DragEnd();
   1203   // w1 is now wider than before.
   1204   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
   1205   // Both windows should get resized since they both don't have min/max size.
   1206   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1207   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1208 
   1209   // Resize the second window left by a bit more and test that the dock expands.
   1210   previous_width = w2->bounds().width();
   1211   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w2.get(),
   1212                                                               0, 20,
   1213                                                               HTLEFT));
   1214   DragMove(-kResizeSpan1, 0);
   1215   DragEnd();
   1216   // Only w2 should get wider since w1 was resized by a user.
   1217   EXPECT_EQ(previous_width + kResizeSpan1, w2->bounds().width());
   1218   // w1 should stays same size as before since it was resized by a user.
   1219   EXPECT_EQ(previous_width, w1->bounds().width());
   1220   EXPECT_EQ(w2->bounds().width(), docked_width(manager));
   1221 
   1222   // Undock w2 and then dock it back.
   1223   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), -400, 100);
   1224   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
   1225   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
   1226   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
   1227   // w2 should become same width as w1.
   1228   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1229   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1230 
   1231   // Make w1 even wider.
   1232   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
   1233                                                               0, 20,
   1234                                                               HTLEFT));
   1235   DragMove(-kResizeSpan1, 0);
   1236   DragEnd();
   1237   // Making w1 wider should make both windows wider since w2 no longer remembers
   1238   // user width.
   1239   EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
   1240   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1241 }
   1242 
   1243 // Tests that dragging a window down to shelf attaches a panel but does not
   1244 // attach a regular window.
   1245 TEST_P(DockedWindowResizerTest, DragToShelf) {
   1246   if (!SupportsHostWindowResize())
   1247     return;
   1248 
   1249   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1250   // Work area should cover the whole screen.
   1251   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width(),
   1252             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width());
   1253 
   1254   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1255   // A window should be docked at the right edge.
   1256   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
   1257             w1->GetBoundsInScreen().right());
   1258   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1259   DockedWindowLayoutManager* manager =
   1260       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
   1261   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1262   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1263 
   1264   // Detach and drag down to shelf.
   1265   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
   1266   DragMove(-40, 0);
   1267   // Alignment is set to "NONE" when drag starts.
   1268   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
   1269   // Release the mouse and the window should be no longer attached to the edge.
   1270   DragEnd();
   1271   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
   1272 
   1273   // Drag down almost to shelf. A panel will snap, a regular window won't.
   1274   ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget();
   1275   const int shelf_y = shelf->GetWindowBoundsInScreen().y();
   1276   const int kDistanceFromShelf = 10;
   1277   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
   1278   DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom());
   1279   DragEnd();
   1280   if (test_panels()) {
   1281     // The panel should be touching the shelf and attached.
   1282     EXPECT_EQ(shelf_y, w1->bounds().bottom());
   1283     EXPECT_TRUE(wm::GetWindowState(w1.get())->panel_attached());
   1284   } else {
   1285     // The window should not be touching the shelf.
   1286     EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom());
   1287   }
   1288 }
   1289 
   1290 // Tests that docking and undocking a |window| with a transient child properly
   1291 // maintains the parent of that transient child to be the same as the |window|.
   1292 TEST_P(DockedWindowResizerTest, DragWindowWithTransientChild) {
   1293   if (!SupportsHostWindowResize())
   1294     return;
   1295 
   1296   // Create a window with a transient child.
   1297   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1298   scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType(
   1299       NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20)));
   1300   window->AddTransientChild(child.get());
   1301   if (window->parent() != child->parent())
   1302     window->parent()->AddChild(child.get());
   1303   EXPECT_EQ(window.get(), child->transient_parent());
   1304 
   1305   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20);
   1306 
   1307   // A window should be docked at the right edge.
   1308   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
   1309   EXPECT_EQ(internal::kShellWindowId_DockedContainer, child->parent()->id());
   1310 
   1311   // Drag the child - it should move freely and stay where it is dragged.
   1312   ASSERT_NO_FATAL_FAILURE(DragStart(child.get()));
   1313   DragMove(500, 20);
   1314   DragEnd();
   1315   EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(),
   1316             child->GetBoundsInScreen().origin().ToString());
   1317 
   1318   // Undock the window by dragging left.
   1319   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
   1320   DragMove(-32, -10);
   1321   DragEnd();
   1322 
   1323   // The window should be undocked and the transient child should be reparented.
   1324   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
   1325   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id());
   1326   // The child should not have moved.
   1327   EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(),
   1328             child->GetBoundsInScreen().origin().ToString());
   1329 }
   1330 
   1331 // Tests that reparenting windows during the drag does not affect system modal
   1332 // windows that are transient children of the dragged windows.
   1333 TEST_P(DockedWindowResizerTest, DragWindowWithModalTransientChild) {
   1334   if (!SupportsHostWindowResize())
   1335     return;
   1336 
   1337   // Create a window.
   1338   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1339   gfx::Rect bounds(window->bounds());
   1340 
   1341   // Start dragging the window.
   1342   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
   1343   gfx::Vector2d move_vector(40, test_panels() ? -60 : 60);
   1344   DragMove(move_vector.x(), move_vector.y());
   1345   EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
   1346 
   1347   // While still dragging create a modal window and make it a transient child of
   1348   // the |window|.
   1349   scoped_ptr<aura::Window> child(CreateModalWindow(gfx::Rect(20, 20, 150, 20)));
   1350   window->AddTransientChild(child.get());
   1351   EXPECT_EQ(window.get(), child->transient_parent());
   1352   EXPECT_EQ(internal::kShellWindowId_SystemModalContainer,
   1353             child->parent()->id());
   1354 
   1355   // End the drag, the |window| should have moved (if it is a panel it will
   1356   // no longer be attached to the shelf since we dragged it above).
   1357   DragEnd();
   1358   bounds.Offset(move_vector);
   1359   EXPECT_EQ(bounds.ToString(), window->GetBoundsInScreen().ToString());
   1360 
   1361   // The original |window| should be in the default container (not docked or
   1362   // attached).
   1363   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
   1364   // The transient |child| should still be in system modal container.
   1365   EXPECT_EQ(internal::kShellWindowId_SystemModalContainer,
   1366             child->parent()->id());
   1367   // The |child| should not have moved.
   1368   EXPECT_EQ(gfx::Point(20, 20).ToString(),
   1369             child->GetBoundsInScreen().origin().ToString());
   1370   // The |child| should still be a transient child of |window|.
   1371   EXPECT_EQ(window.get(), child->transient_parent());
   1372 }
   1373 
   1374 // Tests that side snapping a window undocks it, closes the dock and then snaps.
   1375 TEST_P(DockedWindowResizerTest, SideSnapDocked) {
   1376   if (!SupportsHostWindowResize() || test_panels())
   1377     return;
   1378 
   1379   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1380   wm::WindowState* window_state = wm::GetWindowState(w1.get());
   1381   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1382   // A window should be docked at the right edge.
   1383   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
   1384             w1->GetBoundsInScreen().right());
   1385   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1386   DockedWindowLayoutManager* manager =
   1387       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
   1388   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1389   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1390   EXPECT_TRUE(window_state->IsDocked());
   1391   EXPECT_FALSE(window_state->IsSnapped());
   1392 
   1393   // Side snap at right edge.
   1394   internal::SnapSizer::SnapWindow(window_state,
   1395                                   internal::SnapSizer::RIGHT_EDGE);
   1396   // The window should be snapped at the right edge and the dock should close.
   1397   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()));
   1398   EXPECT_EQ(0, docked_width(manager));
   1399   EXPECT_EQ(work_area.height(), w1->bounds().height());
   1400   EXPECT_EQ(work_area.right(), w1->bounds().right());
   1401   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
   1402   EXPECT_FALSE(window_state->IsDocked());
   1403   EXPECT_TRUE(window_state->IsSnapped());
   1404 
   1405   // Dock again.
   1406   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1407   // A window should be docked at the right edge.
   1408   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
   1409             w1->GetBoundsInScreen().right());
   1410   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1411   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
   1412   EXPECT_EQ(w1->bounds().width(), docked_width(manager));
   1413   EXPECT_TRUE(window_state->IsDocked());
   1414   EXPECT_FALSE(window_state->IsSnapped());
   1415 
   1416   // Side snap at left edge.
   1417   internal::SnapSizer::SnapWindow(window_state,
   1418                                   internal::SnapSizer::LEFT_EDGE);
   1419   // The window should be snapped at the right edge and the dock should close.
   1420   EXPECT_EQ(work_area.ToString(),
   1421             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).ToString());
   1422   EXPECT_EQ(0, docked_width(manager));
   1423   EXPECT_EQ(work_area.height(), w1->bounds().height());
   1424   EXPECT_EQ(work_area.x(), w1->bounds().x());
   1425   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
   1426   EXPECT_FALSE(window_state->IsDocked());
   1427   EXPECT_TRUE(window_state->IsSnapped());
   1428 }
   1429 
   1430 // Tests run twice - on both panels and normal windows
   1431 INSTANTIATE_TEST_CASE_P(NormalOrPanel,
   1432                         DockedWindowResizerTest,
   1433                         testing::Values(aura::client::WINDOW_TYPE_NORMAL,
   1434                                         aura::client::WINDOW_TYPE_PANEL));
   1435 }  // namespace internal
   1436 }  // namespace ash
   1437