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/launcher/launcher_model.h"
     10 #include "ash/root_window_controller.h"
     11 #include "ash/screen_ash.h"
     12 #include "ash/shelf/shelf_layout_manager.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_launcher_delegate.h"
     21 #include "ash/wm/dock/docked_window_layout_manager.h"
     22 #include "ash/wm/drag_window_resizer.h"
     23 #include "ash/wm/panels/panel_layout_manager.h"
     24 #include "ash/wm/window_properties.h"
     25 #include "ash/wm/window_util.h"
     26 #include "base/command_line.h"
     27 #include "ui/aura/client/aura_constants.h"
     28 #include "ui/aura/root_window.h"
     29 #include "ui/aura/test/test_window_delegate.h"
     30 #include "ui/base/hit_test.h"
     31 #include "ui/base/ui_base_types.h"
     32 #include "ui/views/widget/widget.h"
     33 
     34 namespace ash {
     35 namespace internal {
     36 
     37 class DockedWindowResizerTest
     38     : public test::AshTestBase,
     39       public testing::WithParamInterface<aura::client::WindowType> {
     40  public:
     41   DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {}
     42   virtual ~DockedWindowResizerTest() {}
     43 
     44   virtual void SetUp() OVERRIDE {
     45     CommandLine::ForCurrentProcess()->AppendSwitch(
     46         ash::switches::kAshEnableStickyEdges);
     47     CommandLine::ForCurrentProcess()->AppendSwitch(
     48         ash::switches::kAshEnableDockedWindows);
     49     AshTestBase::SetUp();
     50     UpdateDisplay("600x400");
     51     test::ShellTestApi test_api(Shell::GetInstance());
     52     model_ = test_api.launcher_model();
     53   }
     54 
     55   virtual void TearDown() OVERRIDE {
     56     AshTestBase::TearDown();
     57   }
     58 
     59  protected:
     60   enum DockedEdge {
     61     DOCKED_EDGE_NONE,
     62     DOCKED_EDGE_LEFT,
     63     DOCKED_EDGE_RIGHT,
     64   };
     65 
     66   enum DockedState {
     67     UNDOCKED,
     68     DOCKED,
     69   };
     70 
     71   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
     72     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
     73         &delegate_,
     74         window_type_,
     75         0,
     76         bounds);
     77     if (window_type_ == aura::client::WINDOW_TYPE_PANEL) {
     78       test::TestLauncherDelegate* launcher_delegate =
     79           test::TestLauncherDelegate::instance();
     80       launcher_delegate->AddLauncherItem(window);
     81       PanelLayoutManager* manager =
     82           static_cast<PanelLayoutManager*>(
     83               Shell::GetContainer(window->GetRootWindow(),
     84                                   internal::kShellWindowId_PanelContainer)->
     85                   layout_manager());
     86       manager->Relayout();
     87     }
     88     return window;
     89   }
     90 
     91   static WindowResizer* CreateSomeWindowResizer(
     92       aura::Window* window,
     93       const gfx::Point& point_in_parent,
     94       int window_component) {
     95     return CreateWindowResizer(
     96         window,
     97         point_in_parent,
     98         window_component,
     99         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
    100   }
    101 
    102   void DragStart(aura::Window* window) {
    103     initial_location_in_parent_ = window->bounds().origin();
    104     resizer_.reset(CreateSomeWindowResizer(window,
    105                                            initial_location_in_parent_,
    106                                            HTCAPTION));
    107     ASSERT_TRUE(resizer_.get());
    108   }
    109 
    110   void DragStartAtOffsetFromwindowOrigin(aura::Window* window,
    111                                          int dx,
    112                                          int dy) {
    113     initial_location_in_parent_ =
    114         window->bounds().origin() + gfx::Vector2d(dx, dy);
    115     resizer_.reset(CreateSomeWindowResizer(window,
    116                                            initial_location_in_parent_,
    117                                            HTCAPTION));
    118     ASSERT_TRUE(resizer_.get());
    119   }
    120 
    121   void ResizeStartAtOffsetFromwindowOrigin(aura::Window* window,
    122                                            int dx,
    123                                            int dy,
    124                                            int window_component) {
    125     initial_location_in_parent_ =
    126         window->bounds().origin() + gfx::Vector2d(dx, dy);
    127     resizer_.reset(CreateSomeWindowResizer(window,
    128                                            initial_location_in_parent_,
    129                                            window_component));
    130     ASSERT_TRUE(resizer_.get());
    131   }
    132 
    133   void DragMove(int dx, int dy) {
    134     resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0);
    135   }
    136 
    137   void DragEnd() {
    138     resizer_->CompleteDrag(0);
    139     resizer_.reset();
    140   }
    141 
    142   void DragRevert() {
    143     resizer_->RevertDrag();
    144     resizer_.reset();
    145   }
    146 
    147   // Panels are parented by panel container during drags.
    148   // Docked windows are parented by dock container during drags.
    149   // All other windows that we are testing here have default container as a
    150   // parent.
    151   int CorrectContainerIdDuringDrag(DockedState is_docked) {
    152     if (window_type_ == aura::client::WINDOW_TYPE_PANEL)
    153       return internal::kShellWindowId_PanelContainer;
    154     if (is_docked == DOCKED)
    155       return internal::kShellWindowId_DockedContainer;
    156     return internal::kShellWindowId_DefaultContainer;
    157   }
    158 
    159   // Test dragging the window vertically (to detach if it is a panel) and then
    160   // horizontally to the edge with an added offset from the edge of |dx|.
    161   void DragRelativeToEdge(DockedEdge edge,
    162                           aura::Window* window,
    163                           int dx) {
    164     DragVerticallyAndRelativeToEdge(
    165         edge,
    166         window,
    167         dx,
    168         window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20);
    169   }
    170 
    171   void DragToVerticalPositionAndToEdge(DockedEdge edge,
    172                                        aura::Window* window,
    173                                        int y) {
    174     DragToVerticalPositionRelativeToEdge(edge, window, 0, y);
    175   }
    176 
    177   void DragToVerticalPositionRelativeToEdge(DockedEdge edge,
    178                                             aura::Window* window,
    179                                             int dx,
    180                                             int y) {
    181     gfx::Rect initial_bounds = window->GetBoundsInScreen();
    182     DragVerticallyAndRelativeToEdge(edge, window, dx, y - initial_bounds.y());
    183   }
    184 
    185   // Detach if our window is a panel, then drag it vertically by |dy| and
    186   // horizontally to the edge with an added offset from the edge of |dx|.
    187   void DragVerticallyAndRelativeToEdge(DockedEdge edge,
    188                                        aura::Window* window,
    189                                        int dx,
    190                                        int dy) {
    191     aura::RootWindow* root_window = window->GetRootWindow();
    192     gfx::Rect initial_bounds = window->GetBoundsInScreen();
    193 
    194     if (window_type_ == aura::client::WINDOW_TYPE_PANEL) {
    195       ASSERT_NO_FATAL_FAILURE(DragStart(window));
    196       EXPECT_TRUE(window->GetProperty(kPanelAttachedKey));
    197 
    198       // Drag enough to detach since our tests assume panels to be initially
    199       // detached.
    200       DragMove(0, dy);
    201       EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
    202       EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
    203       EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
    204 
    205       // The panel should be detached when the drag completes.
    206       DragEnd();
    207 
    208       EXPECT_FALSE(window->GetProperty(kPanelAttachedKey));
    209       EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    210                 window->parent()->id());
    211       EXPECT_EQ(root_window, window->GetRootWindow());
    212     }
    213 
    214     // avoid snap by clicking away from the border
    215     ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(window, 25, 5));
    216 
    217     // Drag the window left or right to the edge (or almost to it).
    218     if (edge == DOCKED_EDGE_LEFT)
    219       dx += window->GetRootWindow()->bounds().x() - initial_bounds.x();
    220     else if (edge == DOCKED_EDGE_RIGHT)
    221       dx += window->GetRootWindow()->bounds().right() - initial_bounds.right();
    222     DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy);
    223     EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
    224     // Release the mouse and the panel should be attached to the dock.
    225     DragEnd();
    226 
    227     // x-coordinate can get adjusted by snapping or sticking.
    228     // y-coordinate could be changed by possible automatic layout if docked.
    229     if (window->parent()->id() != internal::kShellWindowId_DockedContainer)
    230       EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
    231   }
    232 
    233   bool test_panels() const {
    234     return window_type_ == aura::client::WINDOW_TYPE_PANEL;
    235   }
    236 
    237  private:
    238   scoped_ptr<WindowResizer> resizer_;
    239   LauncherModel* model_;
    240   aura::client::WindowType window_type_;
    241   aura::test::TestWindowDelegate delegate_;
    242 
    243   // Location at start of the drag in |window->parent()|'s coordinates.
    244   gfx::Point initial_location_in_parent_;
    245 
    246   DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest);
    247 };
    248 
    249 // Verifies a window can be dragged and attached to the dock.
    250 TEST_P(DockedWindowResizerTest, AttachRightPrecise) {
    251   if (!SupportsHostWindowResize())
    252     return;
    253 
    254   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    255   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    256 
    257   // The window should be attached and snapped to the right edge.
    258   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    259             window->GetBoundsInScreen().right());
    260   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    261 }
    262 
    263 // Verifies a window can be dragged and attached to the dock
    264 // even if we overshoot the screen edge by a few pixels (sticky edge)
    265 TEST_P(DockedWindowResizerTest, AttachRightOvershoot) {
    266   if (!SupportsHostWindowResize())
    267     return;
    268 
    269   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    270   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4);
    271 
    272   // The window should be attached and snapped to the right edge.
    273   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    274             window->GetBoundsInScreen().right());
    275   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    276 }
    277 
    278 // Verifies a window can be dragged and then if not quite reaching the screen
    279 // edge it does not get docked to a screen edge and stays in the desktop.
    280 TEST_P(DockedWindowResizerTest, AttachRightUndershoot) {
    281   if (!SupportsHostWindowResize())
    282     return;
    283 
    284   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    285   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), -1);
    286 
    287   // The window should not be attached to the dock.
    288   EXPECT_EQ(window->GetRootWindow()->bounds().right() - 1,
    289             window->GetBoundsInScreen().right());
    290   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    291             window->parent()->id());
    292 }
    293 
    294 // Verifies a window can be dragged and attached to the dock.
    295 TEST_P(DockedWindowResizerTest, AttachLeftPrecise) {
    296   if (!SupportsHostWindowResize())
    297     return;
    298 
    299   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    300   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0);
    301 
    302   // The window should be attached and snapped to the left dock.
    303   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    304             window->GetBoundsInScreen().x());
    305   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    306 }
    307 
    308 // Verifies a window can be dragged and attached to the dock
    309 // even if we overshoot the screen edge by a few pixels (sticky edge)
    310 TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) {
    311   if (!SupportsHostWindowResize())
    312     return;
    313 
    314   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    315   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4);
    316 
    317   // The window should be attached and snapped to the left dock.
    318   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    319             window->GetBoundsInScreen().x());
    320   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    321 }
    322 
    323 // Verifies a window can be dragged and then if not quite reaching the screen
    324 // edge it does not get docked to a screen edge and stays in the desktop.
    325 TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) {
    326   if (!SupportsHostWindowResize())
    327     return;
    328 
    329   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    330   DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1);
    331 
    332   // The window should not be attached to the dock.
    333   EXPECT_EQ(window->GetRootWindow()->bounds().x() + 1,
    334             window->GetBoundsInScreen().x());
    335   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    336             window->parent()->id());
    337 }
    338 
    339 // Dock on the right side, change shelf alignment, check that windows move to
    340 // the opposite side.
    341 TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) {
    342   if (!SupportsHostWindowResize())
    343     return;
    344 
    345   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    346   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    347 
    348   // The window should be attached and snapped to the right edge.
    349   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    350             window->GetBoundsInScreen().right());
    351   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    352 
    353   // set launcher shelf to be aligned on the right
    354   ash::Shell* shell = ash::Shell::GetInstance();
    355   shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
    356                            shell->GetPrimaryRootWindow());
    357   // The window should have moved and get attached to the left dock.
    358   EXPECT_EQ(window->GetRootWindow()->bounds().x(),
    359             window->GetBoundsInScreen().x());
    360   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    361 
    362   // set launcher shelf to be aligned on the left
    363   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
    364                            shell->GetPrimaryRootWindow());
    365   // The window should have moved and get attached to the right edge.
    366   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    367             window->GetBoundsInScreen().right());
    368   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    369 
    370   // set launcher shelf to be aligned at the bottom
    371   shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM,
    372                            shell->GetPrimaryRootWindow());
    373   // The window should stay in the right edge.
    374   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    375             window->GetBoundsInScreen().right());
    376   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    377 }
    378 
    379 // Dock on the right side, try to undock, then drag more to really undock
    380 TEST_P(DockedWindowResizerTest, AttachTryDetach) {
    381   if (!SupportsHostWindowResize())
    382     return;
    383 
    384   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    385   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    386 
    387   // The window should be attached and snapped 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   // Try to detach by dragging left a bit (should stay docked)
    393   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    394   DragMove(-10, -10);
    395   // Release the mouse and the window should be still attached to the dock.
    396   DragEnd();
    397 
    398   // The window should be still attached to the right edge.
    399   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    400             window->GetBoundsInScreen().right());
    401   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    402 
    403   // Try to detach by dragging left a bit more (should get undocked)
    404   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    405   DragMove(-32, -10);
    406   // Release the mouse and the window should be no longer attached to the dock.
    407   DragEnd();
    408 
    409   // The window should be floating on the desktop again.
    410   EXPECT_EQ(window->GetRootWindow()->bounds().right() - 32,
    411             window->GetBoundsInScreen().right());
    412   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    413             window->parent()->id());
    414 }
    415 
    416 // Minimize a docked window, then restore it and check that it is still docked.
    417 TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) {
    418   if (!SupportsHostWindowResize())
    419     return;
    420 
    421   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    422   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    423 
    424   // The window should be attached and snapped to the right edge.
    425   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    426             window->GetBoundsInScreen().right());
    427   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    428 
    429   // Minimize the window, it should be hidden.
    430   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
    431   RunAllPendingInMessageLoop();
    432   EXPECT_FALSE(window->IsVisible());
    433   // Restore the window; window should be visible.
    434   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    435   RunAllPendingInMessageLoop();
    436   EXPECT_TRUE(window->IsVisible());
    437 }
    438 
    439 // Dock two windows, undock one, check that the other one is still docked.
    440 TEST_P(DockedWindowResizerTest, AttachTwoWindows)
    441 {
    442   if (!SupportsHostWindowResize())
    443     return;
    444 
    445   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    446   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    447   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    448   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50);
    449 
    450   // Both windows should be attached and snapped to the right edge.
    451   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    452             w1->GetBoundsInScreen().right());
    453   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    454 
    455   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    456             w2->GetBoundsInScreen().right());
    457   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    458 
    459   // Detach by dragging left (should get undocked).
    460   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    461   // Drag up as well to avoid attaching panels to launcher shelf.
    462   DragMove(-32, -100);
    463   // Release the mouse and the window should be no longer attached to the edge.
    464   DragEnd();
    465 
    466   // The first window should be still docked.
    467   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    468             w1->GetBoundsInScreen().right());
    469   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    470 
    471   // The second window should be floating on the desktop again.
    472   EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 32,
    473             w2->GetBoundsInScreen().right());
    474   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    475             w2->parent()->id());
    476 }
    477 
    478 // Dock one window, try to dock another window on the opposite side (should not
    479 // dock).
    480 TEST_P(DockedWindowResizerTest, AttachOnTwoSides)
    481 {
    482   if (!SupportsHostWindowResize())
    483     return;
    484 
    485   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    486   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    487   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    488   DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50);
    489 
    490   // The first window should be attached and snapped to the right edge.
    491   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    492             w1->GetBoundsInScreen().right());
    493   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    494 
    495   // The second window should be near the left edge but not snapped.
    496   EXPECT_EQ(w2->GetRootWindow()->bounds().x(), w2->GetBoundsInScreen().x());
    497   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    498 }
    499 
    500 // Reverting drag
    501 TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) {
    502   if (!SupportsHostWindowResize())
    503     return;
    504 
    505   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    506   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    507 
    508   // The window should be attached and snapped to the right edge.
    509   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    510             window->GetBoundsInScreen().right());
    511   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    512 
    513   // Drag the window out but revert the drag
    514   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    515   DragMove(-50, 0);
    516   DragRevert();
    517   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    518 
    519   // Detach window.
    520   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    521   DragMove(-50, 0);
    522   DragEnd();
    523   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    524             window->parent()->id());
    525 }
    526 
    527 // Move a docked window to the second display
    528 TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
    529   if (!SupportsMultipleDisplays())
    530     return;
    531 
    532   UpdateDisplay("800x800,800x800");
    533   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
    534   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    535   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    536   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    537 
    538   DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
    539   // The window should be attached and snapped to the right edge.
    540   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    541             window->GetBoundsInScreen().right());
    542   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    543 
    544   // Undock and move to the right - enough to get it peeking at the other screen
    545   // but not enough to land in the other screen
    546   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    547   DragMove(70, 0);
    548   EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id());
    549   DragEnd();
    550   EXPECT_NE(window->GetRootWindow()->bounds().right(),
    551             window->GetBoundsInScreen().right());
    552   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    553             window->parent()->id());
    554   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    555 
    556   // Move back left - should dock again.
    557   ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
    558   DragMove(-70, 0);
    559   EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
    560   DragEnd();
    561   EXPECT_EQ(window->GetRootWindow()->bounds().right(),
    562             window->GetBoundsInScreen().right());
    563   EXPECT_EQ(internal::kShellWindowId_DockedContainer,
    564             window->parent()->id());
    565   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    566 
    567   // Undock and move to the right - enough to get the mouse pointer past the
    568   // edge of the screen and into the second screen. The window should now be
    569   // in the second screen and not docked.
    570   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(
    571       window.get(),
    572       window->bounds().width()/2 + 10,
    573       0));
    574   DragMove(window->bounds().width()/2 - 5, 0);
    575   EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id());
    576   DragEnd();
    577   EXPECT_NE(window->GetRootWindow()->bounds().right(),
    578             window->GetBoundsInScreen().right());
    579   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
    580             window->parent()->id());
    581   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    582 
    583   // Keep dragging it to the right until it docks. The window should now be
    584   // in the second screen.
    585   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(
    586       window.get(),
    587       window->bounds().width()/2 + 10,
    588       0));
    589   DragMove(window->GetRootWindow()->GetBoundsInScreen().x() -
    590            window->GetBoundsInScreen().x(),
    591            0);
    592   EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
    593   DragEnd();
    594   EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
    595             window->GetBoundsInScreen().x());
    596   EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
    597   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    598 }
    599 
    600 // Dock two windows, undock one.
    601 // Test the docked windows area size and default container resizing.
    602 TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne)
    603 {
    604   if (!SupportsHostWindowResize())
    605     return;
    606 
    607   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    608   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    609   // Work area should cover the whole screen.
    610   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    611             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    612 
    613   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    614   // A window should be attached and snapped to the right edge.
    615   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    616             w1->GetBoundsInScreen().right());
    617   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    618   DockedWindowLayoutManager* manager =
    619       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    620   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    621   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    622 
    623   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50);
    624   // Both windows should now be attached and snapped to the right edge.
    625   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    626             w2->GetBoundsInScreen().right());
    627   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    628   // Dock width should be set to a wider window.
    629   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    630   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
    631             manager->docked_width_);
    632 
    633   // Try to detach by dragging left a bit (should not get undocked).
    634   // This would normally detach a single docked window but since we have another
    635   // window and the mouse pointer does not leave the dock area the window
    636   // should stay docked.
    637   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 60, 0));
    638   // Drag up as well as left to avoid attaching panels to launcher shelf.
    639   DragMove(-40, -40);
    640   // Release the mouse and the window should be still attached to the edge.
    641   DragEnd();
    642 
    643   // The first window should be still docked.
    644   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    645             w1->GetBoundsInScreen().right());
    646   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    647 
    648   // The second window should be still docked.
    649   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    650             w2->GetBoundsInScreen().right());
    651   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    652 
    653   // Detach by dragging left more (should get undocked).
    654   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(
    655       w2.get(),
    656       w2->bounds().width()/2 + 10,
    657       0));
    658   // Drag up as well to avoid attaching panels to launcher shelf.
    659   DragMove(-(w2->bounds().width()/2 + 20), -100);
    660   // Release the mouse and the window should be no longer attached to the edge.
    661   DragEnd();
    662 
    663   // The second window should be floating on the desktop again.
    664   EXPECT_EQ(w2->GetRootWindow()->bounds().right() -
    665             (w2->bounds().width()/2 + 20),
    666             w2->GetBoundsInScreen().right());
    667   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    668   // Dock width should be set to remaining single docked window.
    669   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    670   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    671   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    672 }
    673 
    674 // Dock one windows. Maximize other testing desktop resizing.
    675 TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther)
    676 {
    677   if (!SupportsHostWindowResize())
    678     return;
    679 
    680   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    681   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    682   // Work area should cover the whole screen.
    683   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    684             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    685 
    686   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    687   // A window should be attached and snapped to the right edge.
    688   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    689             w1->GetBoundsInScreen().right());
    690   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    691   DockedWindowLayoutManager* manager =
    692       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    693   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    694   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    695 
    696   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT,
    697                                        w2.get(),
    698                                        -(w2->bounds().width()/2 + 20),
    699                                        50);
    700   // The first window should be still docked.
    701   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    702             w1->GetBoundsInScreen().right());
    703   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    704 
    705   // The second window should be floating on the desktop.
    706   EXPECT_EQ(w2->GetRootWindow()->bounds().right() -
    707             (w2->bounds().width()/2 + 20),
    708             w2->GetBoundsInScreen().right());
    709   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    710   // Dock width should be set to remaining single docked window.
    711   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    712   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    713   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    714   // Desktop work area should now shrink.
    715   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    716             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    717             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    718 
    719   // Maximize the second window - Maximized area should be shrunk.
    720   const gfx::Rect restored_bounds = w2->bounds();
    721   wm::MaximizeWindow(w2.get());
    722   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    723             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    724             w2->bounds().width());
    725 
    726   // Detach the first window (this should require very little drag).
    727   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
    728   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    729   DragMove(-35, 10);
    730   // For NORMAL windows alignment is set to "RIGHT" until the drag is completed.
    731   // For PANEL windows alignment is set to "NONE" when drag starts.
    732   EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT,
    733             manager->alignment_);
    734   // Release the mouse and the window should be no longer attached to the edge.
    735   DragEnd();
    736   // Dock should get shrunk and desktop should get expanded.
    737   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
    738   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    739   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
    740   EXPECT_EQ(0, manager->docked_width_);
    741   // The second window should now get resized and take up the whole screen.
    742   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    743             w2->bounds().width());
    744 
    745   // Dock the first window to the left edge.
    746   // Click at an offset from origin to prevent snapping.
    747   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 10, 0));
    748   DragMove(-w1->bounds().x(), 0);
    749   // Alignment set to "NONE" during the drag of the window when none are docked.
    750   EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
    751   // Release the mouse and the window should be now attached to the edge.
    752   DragEnd();
    753   // Dock should get expanded and desktop should get shrunk.
    754   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    755   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    756   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    757   // Second window should still be in the desktop.
    758   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    759   // Maximized window should be shrunk.
    760   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    761             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    762             w2->bounds().width());
    763 
    764   // Unmaximize the second window.
    765   wm::RestoreWindow(w2.get());
    766   // Its bounds should get restored.
    767   EXPECT_EQ(restored_bounds, w2->bounds());
    768 }
    769 
    770 // Dock one window. Test the sticky behavior near screen or desktop edge.
    771 TEST_P(DockedWindowResizerTest, AttachOneTestSticky)
    772 {
    773   if (!SupportsHostWindowResize())
    774     return;
    775 
    776   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    777   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    778   // Work area should cover the whole screen.
    779   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    780             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    781 
    782   DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20);
    783   // A window should be attached and snapped to the left edge.
    784   EXPECT_EQ(w1->GetRootWindow()->bounds().x(),
    785             w1->GetBoundsInScreen().x());
    786   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    787   DockedWindowLayoutManager* manager =
    788       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    789   // The first window should be docked.
    790   EXPECT_EQ(w1->GetRootWindow()->bounds().x(),
    791             w1->GetBoundsInScreen().x());
    792   // Dock width should be set to that of a single docked window.
    793   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    794   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    795   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    796 
    797   // Position second window in the desktop just to the right of the docked w1.
    798   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT,
    799                                        w2.get(),
    800                                        w1->bounds().right() + 20,
    801                                        50);
    802   // The second window should be floating on the desktop.
    803   EXPECT_EQ(w2->GetRootWindow()->bounds().x() + (w1->bounds().right() + 20),
    804             w2->GetBoundsInScreen().x());
    805   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    806   // Dock width should be set to that of a single docked window.
    807   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    808   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    809   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    810 
    811   // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock.
    812   ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 10, 0));
    813   DragMove(1 + manager->docked_width_ - w2->bounds().x(), 0);
    814   // Alignment set to "LEFT" during the drag because dock has a window in it.
    815   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    816   // Release the mouse and the window should not be attached to the edge.
    817   DragEnd();
    818   // Dock should still have only one window in it.
    819   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    820   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    821   // The second window should still be in the desktop.
    822   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    823   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    824 
    825   // Drag w2 by a bit more - it should resist the drag (stuck edges)
    826   int start_x = w2->bounds().x();
    827   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    828   DragMove(-2, 0);
    829   // Window should not actually move.
    830   EXPECT_EQ(start_x, w2->bounds().x());
    831   // Alignment set to "LEFT" during the drag because dock has a window in it.
    832   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    833   // Release the mouse and the window should not be attached to the edge.
    834   DragEnd();
    835   // Window should be still where it was before the last drag started.
    836   EXPECT_EQ(start_x, w2->bounds().x());
    837   // Dock should still have only one window in it
    838   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    839   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    840   // The second window should still be in the desktop
    841   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    842   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
    843 
    844   // Drag w2 by more than the stuck threshold and drop it into the dock.
    845   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    846   DragMove(-100, 0);
    847   // Window should actually move.
    848   EXPECT_NE(start_x, w2->bounds().x());
    849   // Alignment set to "LEFT" during the drag because dock has a window in it.
    850   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    851   // Release the mouse and the window should be attached to the edge.
    852   DragEnd();
    853   // Both windows are docked now.
    854   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    855   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    856   // Dock should get expanded and desktop should get shrunk.
    857   EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_);
    858   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
    859             manager->docked_width_);
    860   // Desktop work area should now shrink by dock width.
    861   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    862             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    863             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    864 }
    865 
    866 // Dock two windows, resize one or both.
    867 // Test the docked windows area size and remaining desktop resizing.
    868 TEST_P(DockedWindowResizerTest, ResizeTwoWindows)
    869 {
    870   if (!SupportsHostWindowResize())
    871     return;
    872 
    873   // Wider display to start since panels are limited to half the display width.
    874   UpdateDisplay("1000x400");
    875   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
    876   scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
    877   // Work area should cover the whole screen.
    878   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(),
    879             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    880 
    881   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
    882   // A window should be attached and snapped to the right edge.
    883   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
    884             w1->GetBoundsInScreen().right());
    885   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    886   DockedWindowLayoutManager* manager =
    887       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
    888   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    889   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    890 
    891   DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50);
    892   // Both windows should now be attached and snapped to the right edge.
    893   EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
    894             w2->GetBoundsInScreen().right());
    895   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    896   // Dock width should be set to a wider window.
    897   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    898   EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
    899             manager->docked_width_);
    900 
    901   // Resize the first window left by a bit and test that the dock expands.
    902   int previous_width = w1->bounds().width();
    903   const int kResizeSpan1 = 30;
    904   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(),
    905                                                               0,
    906                                                               20,
    907                                                               HTLEFT));
    908   DragMove(-kResizeSpan1, 0);
    909   // Alignment set to "RIGHT" during the drag because dock has a window in it.
    910   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    911   // Release the mouse and the window should be attached to the edge.
    912   DragEnd();
    913   // Dock should still have both windows in it.
    914   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    915   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    916   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    917   // w1 is now wider than w2 and the dock should expand and be as wide as w1.
    918   EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
    919   EXPECT_GT(w1->bounds().width(), w2->bounds().width());
    920   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    921   // Desktop work area should shrink.
    922   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    923             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    924             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    925 
    926   // Resize the first window left by more than the dock maximum width.
    927   // This should cause the window to overhang and the dock to shrink to w2.
    928   previous_width = w1->bounds().width();
    929   const int kResizeSpan2 = 250;
    930   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(),
    931                                                               0,
    932                                                               20,
    933                                                               HTLEFT));
    934   DragMove(-kResizeSpan2, 0);
    935   // Alignment set to "RIGHT" during the drag because dock has a window in it.
    936   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    937   // Release the mouse and the window should be attached to the edge.
    938   DragEnd();
    939   // Dock should still have both windows in it.
    940   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    941   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    942   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    943   // w1 is now wider than the maximum dock width and the dock should shrink to
    944   // the next widest window (w2).
    945   EXPECT_EQ(previous_width + kResizeSpan2, w1->bounds().width());
    946   EXPECT_GT(w1->bounds().width(), w2->bounds().width());
    947   EXPECT_EQ(w2->bounds().width(), manager->docked_width_);
    948   // Desktop work area should shrink.
    949   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    950             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    951             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    952 
    953   // Resize the first window right to get it completely inside the docked area.
    954   previous_width = w1->bounds().width();
    955   const int kResizeSpan3 = 100;
    956   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(),
    957                                                               0,
    958                                                               20,
    959                                                               HTLEFT));
    960   DragMove(kResizeSpan3, 0);
    961   // Alignment set to "RIGHT" during the drag because dock has a window in it.
    962   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    963   // Release the mouse and the window should be attached to the edge.
    964   DragEnd();
    965   // Dock should still have both windows in it.
    966   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    967   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
    968   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    969   // w1 is still wider than w2 so the dock should expand and be as wide as w1.
    970   EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width());
    971   EXPECT_GT(w1->bounds().width(), w2->bounds().width());
    972   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
    973   // Desktop work area should shrink.
    974   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
    975             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
    976             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
    977 
    978   // Resize the first window left to be overhang again.
    979   previous_width = w1->bounds().width();
    980   ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(),
    981                                                               0,
    982                                                               20,
    983                                                               HTLEFT));
    984   DragMove(-kResizeSpan3, 0);
    985   DragEnd();
    986   EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width());
    987   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
    988   // Docked area should be as wide as the second window - the first is too wide.
    989   EXPECT_EQ(w2->bounds().width(), manager->docked_width_);
    990 
    991   // Undock the second window. Docked area should shrink to its minimum size.
    992   ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
    993   // Drag up as well to avoid attaching panels to launcher shelf.
    994   DragMove(-40, -100);
    995   // Alignment set to "RIGHT" since we have another window docked.
    996   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
    997   // Release the mouse and the window should be no longer attached to the edge.
    998   DragEnd();
    999   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
   1000   // Dock should get shrunk to minimum size.
   1001   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
   1002   EXPECT_EQ(manager->kMinDockWidth, manager->docked_width_);
   1003   // The first window should be still docked.
   1004   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1005   // Desktop work area should be inset.
   1006   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() -
   1007             manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap,
   1008             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
   1009 }
   1010 
   1011 TEST_P(DockedWindowResizerTest, DragToShelf)
   1012 {
   1013   if (!SupportsHostWindowResize())
   1014     return;
   1015 
   1016   scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
   1017   // Work area should cover the whole screen.
   1018   EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width(),
   1019             ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width());
   1020 
   1021   DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
   1022   // A window should be attached and snapped to the right edge.
   1023   EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
   1024             w1->GetBoundsInScreen().right());
   1025   EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
   1026   DockedWindowLayoutManager* manager =
   1027       static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
   1028   EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
   1029   EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
   1030 
   1031   // Detach and drag down to shelf.
   1032   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
   1033   DragMove(-40, 0);
   1034   // For NORMAL windows alignment is set to "RIGHT" until the drag is completed.
   1035   // For PANEL windows alignment is set to "NONE" when drag starts.
   1036   EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT,
   1037             manager->alignment_);
   1038   // Release the mouse and the window should be no longer attached to the edge.
   1039   DragEnd();
   1040 
   1041   // Drag down almost to shelf. A panel will snap, a regular window won't.
   1042   ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget();
   1043   const int shelf_y = shelf->GetWindowBoundsInScreen().y();
   1044   const int kDistanceFromShelf = 10;
   1045   ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
   1046   DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom());
   1047   DragEnd();
   1048   if (test_panels()) {
   1049     // The panel should be touching the shelf and attached.
   1050     EXPECT_EQ(shelf_y, w1->bounds().bottom());
   1051     EXPECT_TRUE(w1->GetProperty(kPanelAttachedKey));
   1052   } else {
   1053     // The window should not be touching the shelf.
   1054     EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom());
   1055   }
   1056 }
   1057 
   1058 // Tests run twice - on both panels and normal windows
   1059 INSTANTIATE_TEST_CASE_P(NormalOrPanel,
   1060                         DockedWindowResizerTest,
   1061                         testing::Values(aura::client::WINDOW_TYPE_NORMAL,
   1062                                         aura::client::WINDOW_TYPE_PANEL));
   1063 }  // namespace internal
   1064 }  // namespace ash
   1065