Home | History | Annotate | Download | only in panels
      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/panels/panel_window_resizer.h"
      6 
      7 #include "ash/root_window_controller.h"
      8 #include "ash/shelf/shelf.h"
      9 #include "ash/shelf/shelf_layout_manager.h"
     10 #include "ash/shelf/shelf_model.h"
     11 #include "ash/shelf/shelf_types.h"
     12 #include "ash/shelf/shelf_util.h"
     13 #include "ash/shelf/shelf_widget.h"
     14 #include "ash/shell.h"
     15 #include "ash/shell_window_ids.h"
     16 #include "ash/test/ash_test_base.h"
     17 #include "ash/test/cursor_manager_test_api.h"
     18 #include "ash/test/shell_test_api.h"
     19 #include "ash/test/test_shelf_delegate.h"
     20 #include "ash/wm/drag_window_resizer.h"
     21 #include "ash/wm/panels/panel_layout_manager.h"
     22 #include "ash/wm/window_state.h"
     23 #include "ash/wm/wm_event.h"
     24 #include "base/win/windows_version.h"
     25 #include "ui/aura/client/aura_constants.h"
     26 #include "ui/aura/window_event_dispatcher.h"
     27 #include "ui/base/hit_test.h"
     28 #include "ui/base/l10n/l10n_util.h"
     29 #include "ui/base/ui_base_types.h"
     30 #include "ui/views/widget/widget.h"
     31 #include "ui/wm/core/window_util.h"
     32 
     33 namespace ash {
     34 
     35 class PanelWindowResizerTest : public test::AshTestBase {
     36  public:
     37   PanelWindowResizerTest() {}
     38   virtual ~PanelWindowResizerTest() {}
     39 
     40   virtual void SetUp() OVERRIDE {
     41     AshTestBase::SetUp();
     42     UpdateDisplay("600x400");
     43     test::ShellTestApi test_api(Shell::GetInstance());
     44     model_ = test_api.shelf_model();
     45     shelf_delegate_ = test::TestShelfDelegate::instance();
     46   }
     47 
     48   virtual void TearDown() OVERRIDE {
     49     AshTestBase::TearDown();
     50   }
     51 
     52  protected:
     53   gfx::Point CalculateDragPoint(const WindowResizer& resizer,
     54                                 int delta_x,
     55                                 int delta_y) const {
     56     gfx::Point location = resizer.GetInitialLocation();
     57     location.set_x(location.x() + delta_x);
     58     location.set_y(location.y() + delta_y);
     59     return location;
     60   }
     61 
     62   aura::Window* CreatePanelWindow(const gfx::Point& origin) {
     63     gfx::Rect bounds(origin, gfx::Size(101, 101));
     64     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
     65         NULL, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
     66     shelf_delegate_->AddShelfItem(window);
     67     return window;
     68   }
     69 
     70   void DragStart(aura::Window* window) {
     71     resizer_.reset(CreateWindowResizer(
     72         window,
     73         window->bounds().origin(),
     74         HTCAPTION,
     75         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release());
     76     ASSERT_TRUE(resizer_.get());
     77   }
     78 
     79   void DragMove(int dx, int dy) {
     80     resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0);
     81   }
     82 
     83   void DragEnd() {
     84     resizer_->CompleteDrag();
     85     resizer_.reset();
     86   }
     87 
     88   void DragRevert() {
     89     resizer_->RevertDrag();
     90     resizer_.reset();
     91   }
     92 
     93   // Test dragging the panel slightly, then detaching, and then reattaching
     94   // dragging out by the vector (dx, dy).
     95   void DetachReattachTest(aura::Window* window, int dx, int dy) {
     96     wm::WindowState* window_state = wm::GetWindowState(window);
     97     EXPECT_TRUE(window_state->panel_attached());
     98     aura::Window* root_window = window->GetRootWindow();
     99     EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    100     DragStart(window);
    101     gfx::Rect initial_bounds = window->GetBoundsInScreen();
    102 
    103     // Drag the panel slightly. The window should still be snapped to the
    104     // launcher.
    105     DragMove(dx * 5, dy * 5);
    106     EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
    107     EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
    108 
    109     // Drag further out and the window should now move to the cursor.
    110     DragMove(dx * 100, dy * 100);
    111     EXPECT_EQ(initial_bounds.x() + dx * 100, window->GetBoundsInScreen().x());
    112     EXPECT_EQ(initial_bounds.y() + dy * 100, window->GetBoundsInScreen().y());
    113 
    114     // The panel should be detached when the drag completes.
    115     DragEnd();
    116 
    117     EXPECT_FALSE(window_state->panel_attached());
    118     EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    119     EXPECT_EQ(root_window, window->GetRootWindow());
    120 
    121     DragStart(window);
    122     // Drag the panel down.
    123     DragMove(dx * -95, dy * -95);
    124     // Release the mouse and the panel should be reattached.
    125     DragEnd();
    126 
    127     // The panel should be reattached and have snapped to the launcher.
    128     EXPECT_TRUE(window_state->panel_attached());
    129     EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
    130     EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
    131     EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    132   }
    133 
    134   void TestWindowOrder(const std::vector<aura::Window*>& window_order) {
    135     int panel_index = model_->FirstPanelIndex();
    136     EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count());
    137     for (std::vector<aura::Window*>::const_iterator iter =
    138          window_order.begin(); iter != window_order.end();
    139          ++iter, ++panel_index) {
    140       ShelfID id = GetShelfIDForWindow(*iter);
    141       EXPECT_EQ(id, model_->items()[panel_index].id);
    142     }
    143   }
    144 
    145   // Test dragging panel window along the shelf and verify that panel icons
    146   // are reordered appropriately.
    147   void DragAlongShelfReorder(int dx, int dy) {
    148     gfx::Point origin(0, 0);
    149     scoped_ptr<aura::Window> w1(CreatePanelWindow(origin));
    150     scoped_ptr<aura::Window> w2(CreatePanelWindow(origin));
    151     std::vector<aura::Window*> window_order_original;
    152     std::vector<aura::Window*> window_order_swapped;
    153     window_order_original.push_back(w1.get());
    154     window_order_original.push_back(w2.get());
    155     window_order_swapped.push_back(w2.get());
    156     window_order_swapped.push_back(w1.get());
    157     TestWindowOrder(window_order_original);
    158 
    159     // Drag window #2 to the beginning of the shelf.
    160     DragStart(w2.get());
    161     DragMove(400 * dx, 400 * dy);
    162     TestWindowOrder(window_order_swapped);
    163     DragEnd();
    164 
    165     // Expect swapped window order.
    166     TestWindowOrder(window_order_swapped);
    167 
    168     // Drag window #2 back to the end.
    169     DragStart(w2.get());
    170     DragMove(-400 * dx, -400 * dy);
    171     TestWindowOrder(window_order_original);
    172     DragEnd();
    173 
    174     // Expect original order.
    175     TestWindowOrder(window_order_original);
    176   }
    177 
    178  private:
    179   scoped_ptr<WindowResizer> resizer_;
    180   PanelLayoutManager* panel_layout_manager_;
    181   ShelfModel* model_;
    182   test::TestShelfDelegate* shelf_delegate_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest);
    185 };
    186 
    187 class PanelWindowResizerTextDirectionTest
    188     : public PanelWindowResizerTest,
    189       public testing::WithParamInterface<bool> {
    190  public:
    191   PanelWindowResizerTextDirectionTest() : is_rtl_(GetParam()) {}
    192   virtual ~PanelWindowResizerTextDirectionTest() {}
    193 
    194   virtual void SetUp() OVERRIDE {
    195     original_locale = l10n_util::GetApplicationLocale(std::string());
    196     if (is_rtl_)
    197       base::i18n::SetICUDefaultLocale("he");
    198     PanelWindowResizerTest::SetUp();
    199     ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
    200   }
    201 
    202   virtual void TearDown() OVERRIDE {
    203     if (is_rtl_)
    204       base::i18n::SetICUDefaultLocale(original_locale);
    205     PanelWindowResizerTest::TearDown();
    206   }
    207 
    208  private:
    209   bool is_rtl_;
    210   std::string original_locale;
    211 
    212   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTextDirectionTest);
    213 };
    214 
    215 // PanelLayoutManager and PanelWindowResizer should work if panels have
    216 // transient children of supported types.
    217 class PanelWindowResizerTransientTest
    218     : public PanelWindowResizerTest,
    219       public testing::WithParamInterface<ui::wm::WindowType> {
    220  public:
    221   PanelWindowResizerTransientTest() : transient_window_type_(GetParam()) {}
    222   virtual ~PanelWindowResizerTransientTest() {}
    223 
    224  protected:
    225   ui::wm::WindowType transient_window_type_;
    226 
    227  private:
    228   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTransientTest);
    229 };
    230 
    231 // Verifies a window can be dragged from the panel and detached and then
    232 // reattached.
    233 TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) {
    234  if (!SupportsHostWindowResize())
    235     return;
    236 
    237   scoped_ptr<aura::Window> window(
    238       CreatePanelWindow(gfx::Point(0, 0)));
    239   DetachReattachTest(window.get(), 0, -1);
    240 }
    241 
    242 TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) {
    243  if (!SupportsHostWindowResize())
    244     return;
    245 
    246   ash::Shell* shell = ash::Shell::GetInstance();
    247   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
    248   scoped_ptr<aura::Window> window(
    249       CreatePanelWindow(gfx::Point(0, 0)));
    250   DetachReattachTest(window.get(), 1, 0);
    251 }
    252 
    253 TEST_F(PanelWindowResizerTest, PanelDetachReattachRight) {
    254   if (!SupportsHostWindowResize())
    255     return;
    256 
    257   ash::Shell* shell = ash::Shell::GetInstance();
    258   shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
    259                            shell->GetPrimaryRootWindow());
    260   scoped_ptr<aura::Window> window(
    261       CreatePanelWindow(gfx::Point(0, 0)));
    262   DetachReattachTest(window.get(), -1, 0);
    263 }
    264 
    265 TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) {
    266  if (!SupportsHostWindowResize())
    267     return;
    268 
    269   ash::Shell* shell = ash::Shell::GetInstance();
    270   shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow());
    271   scoped_ptr<aura::Window> window(
    272       CreatePanelWindow(gfx::Point(0, 0)));
    273   DetachReattachTest(window.get(), 0, 1);
    274 }
    275 
    276 // Tests that a drag continues when the shelf is hidden. This occurs as part of
    277 // the animation when switching profiles. http://crbug.com/393047.
    278 TEST_F(PanelWindowResizerTest, DetachThenHideShelf) {
    279   if (!SupportsHostWindowResize())
    280     return;
    281   scoped_ptr<aura::Window> window(
    282       CreatePanelWindow(gfx::Point(0, 0)));
    283   wm::WindowState* state = wm::GetWindowState(window.get());
    284   gfx::Rect expected_bounds = window->GetBoundsInScreen();
    285   expected_bounds.set_y(expected_bounds.y() - 100);
    286   DragStart(window.get());
    287   DragMove(0, -100);
    288   EXPECT_FALSE(state->IsMinimized());
    289 
    290   // Hide the shelf. This minimizes all attached windows but should ignore
    291   // the dragged window.
    292   ShelfLayoutManager* shelf = RootWindowController::ForWindow(window.get())->
    293       shelf()->shelf_layout_manager();
    294   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
    295   shelf->UpdateVisibilityState();
    296   RunAllPendingInMessageLoop();
    297   EXPECT_FALSE(state->IsMinimized());
    298   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    299   DragEnd();
    300 
    301   // When the drag ends the window should be detached and placed where it was
    302   // dragged to.
    303   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    304   EXPECT_FALSE(state->IsMinimized());
    305   EXPECT_EQ(expected_bounds.ToString(), window->GetBoundsInScreen().ToString());
    306 }
    307 
    308 TEST_F(PanelWindowResizerTest, PanelDetachReattachMultipleDisplays) {
    309   if (!SupportsMultipleDisplays())
    310     return;
    311 
    312   UpdateDisplay("600x400,600x400");
    313   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    314   scoped_ptr<aura::Window> window(
    315       CreatePanelWindow(gfx::Point(600, 0)));
    316   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    317   DetachReattachTest(window.get(), 0, -1);
    318 }
    319 
    320 TEST_F(PanelWindowResizerTest, DetachThenDragAcrossDisplays) {
    321   if (!SupportsMultipleDisplays())
    322     return;
    323 
    324   UpdateDisplay("600x400,600x400");
    325   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    326   scoped_ptr<aura::Window> window(
    327       CreatePanelWindow(gfx::Point(0, 0)));
    328   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    329   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    330   DragStart(window.get());
    331   DragMove(0, -100);
    332   DragEnd();
    333   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    334   EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
    335   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
    336   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    337   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    338 
    339   DragStart(window.get());
    340   DragMove(500, 0);
    341   DragEnd();
    342   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    343   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
    344   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
    345   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    346   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    347 }
    348 
    349 TEST_F(PanelWindowResizerTest, DetachAcrossDisplays) {
    350   if (!SupportsMultipleDisplays())
    351     return;
    352 
    353   UpdateDisplay("600x400,600x400");
    354   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    355   scoped_ptr<aura::Window> window(
    356       CreatePanelWindow(gfx::Point(0, 0)));
    357   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    358   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    359   DragStart(window.get());
    360   DragMove(500, -100);
    361   DragEnd();
    362   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    363   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
    364   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
    365   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    366   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    367 }
    368 
    369 TEST_F(PanelWindowResizerTest, DetachThenAttachToSecondDisplay) {
    370   if (!SupportsMultipleDisplays())
    371     return;
    372 
    373   UpdateDisplay("600x400,600x600");
    374   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    375   scoped_ptr<aura::Window> window(
    376       CreatePanelWindow(gfx::Point(0, 0)));
    377   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    378   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    379 
    380   // Detach the window.
    381   DragStart(window.get());
    382   DragMove(0, -100);
    383   DragEnd();
    384   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    385   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    386 
    387   // Drag the window just above the other display's launcher.
    388   DragStart(window.get());
    389   DragMove(500, 295);
    390   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
    391 
    392   // Should stick to other launcher.
    393   EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
    394   DragEnd();
    395 
    396   // When dropped should move to second display's panel container.
    397   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    398   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
    399   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    400 }
    401 
    402 TEST_F(PanelWindowResizerTest, AttachToSecondDisplay) {
    403   if (!SupportsMultipleDisplays())
    404     return;
    405 
    406   UpdateDisplay("600x400,600x600");
    407   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    408   scoped_ptr<aura::Window> window(
    409       CreatePanelWindow(gfx::Point(0, 0)));
    410   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    411   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    412 
    413   // Drag the window just above the other display's launcher.
    414   DragStart(window.get());
    415   DragMove(500, 195);
    416   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
    417 
    418   // Should stick to other launcher.
    419   EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
    420   DragEnd();
    421 
    422   // When dropped should move to second display's panel container.
    423   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    424   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
    425   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    426 }
    427 
    428 TEST_F(PanelWindowResizerTest, AttachToSecondFullscreenDisplay) {
    429   if (!SupportsMultipleDisplays())
    430     return;
    431 
    432   UpdateDisplay("600x400,600x600");
    433   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    434   scoped_ptr<aura::Window> window(
    435       CreatePanelWindow(gfx::Point(0, 0)));
    436   scoped_ptr<aura::Window> fullscreen(
    437       CreateTestWindowInShellWithBounds(gfx::Rect(600, 0, 101, 101)));
    438   wm::GetWindowState(fullscreen.get())->Activate();
    439   const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
    440   wm::GetWindowState(fullscreen.get())->OnWMEvent(&event);
    441   EXPECT_TRUE(wm::GetWindowState(fullscreen.get())->IsFullscreen());
    442 
    443   gfx::Rect initial_bounds = window->GetBoundsInScreen();
    444   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    445 
    446   // Activate and drag the window to the other display's launcher.
    447   wm::GetWindowState(window.get())->Activate();
    448   DragStart(window.get());
    449   DragMove(500, 250);
    450   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
    451   EXPECT_GT(window->GetBoundsInScreen().y(),
    452             initial_bounds.y() + 200);
    453   DragEnd();
    454 
    455   // When dropped should move to second display's panel container.
    456   EXPECT_EQ(root_windows[1], window->GetRootWindow());
    457   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
    458   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    459   EXPECT_TRUE(window->IsVisible());
    460   EXPECT_TRUE(wm::GetWindowState(window.get())->IsActive());
    461   EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
    462 }
    463 
    464 TEST_F(PanelWindowResizerTest, RevertDragRestoresAttachment) {
    465   scoped_ptr<aura::Window> window(
    466       CreatePanelWindow(gfx::Point(0, 0)));
    467   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
    468   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    469   DragStart(window.get());
    470   DragMove(0, -100);
    471   DragRevert();
    472   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
    473   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    474 
    475   // Detach panel.
    476   DragStart(window.get());
    477   DragMove(0, -100);
    478   DragEnd();
    479   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    480   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    481 
    482   // Drag back to launcher.
    483   DragStart(window.get());
    484   DragMove(0, 100);
    485 
    486   // When the drag is reverted it should remain detached.
    487   DragRevert();
    488   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
    489   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    490 }
    491 
    492 TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) {
    493   scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
    494   DragStart(window.get());
    495   DragMove(0, -100);
    496   DragEnd();
    497   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    498 
    499   // While moving the panel window should be moved to the panel container.
    500   DragStart(window.get());
    501   DragMove(20, 0);
    502   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    503   DragEnd();
    504 
    505   // When dropped it should return to the default container.
    506   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    507 }
    508 
    509 TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) {
    510   if (!SupportsHostWindowResize())
    511     return;
    512 
    513   DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0);
    514 }
    515 
    516 TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) {
    517   if (!SupportsHostWindowResize())
    518     return;
    519 
    520   ash::Shell* shell = ash::Shell::GetInstance();
    521   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
    522   DragAlongShelfReorder(0, -1);
    523 }
    524 
    525 // Tests that panels can have transient children of different types.
    526 // The transient children should be reparented in sync with the panel.
    527 TEST_P(PanelWindowResizerTransientTest, PanelWithTransientChild) {
    528   if (!SupportsHostWindowResize())
    529     return;
    530 
    531   scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
    532   scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType(
    533       NULL, transient_window_type_, 0, gfx::Rect(20, 20, 150, 40)));
    534   ::wm::AddTransientChild(window.get(), child.get());
    535   if (window->parent() != child->parent())
    536     window->parent()->AddChild(child.get());
    537   EXPECT_EQ(window.get(), ::wm::GetTransientParent(child.get()));
    538 
    539   // Drag the child to the shelf. Its new position should not be overridden.
    540   const gfx::Rect attached_bounds(window->GetBoundsInScreen());
    541   const int dy = window->GetBoundsInScreen().bottom() -
    542       child->GetBoundsInScreen().bottom();
    543   DragStart(child.get());
    544   DragMove(50, dy);
    545   // While moving the transient child window should be in the panel container.
    546   EXPECT_EQ(kShellWindowId_PanelContainer, child->parent()->id());
    547   DragEnd();
    548   // Child should move, |window| should not.
    549   EXPECT_EQ(gfx::Point(20 + 50, 20 + dy).ToString(),
    550             child->GetBoundsInScreen().origin().ToString());
    551   EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
    552 
    553   // Drag the child along the the shelf past the |window|.
    554   // Its new position should not be overridden.
    555   DragStart(child.get());
    556   DragMove(350, 0);
    557   // While moving the transient child window should be in the panel container.
    558   EXPECT_EQ(kShellWindowId_PanelContainer, child->parent()->id());
    559   DragEnd();
    560   // |child| should move, |window| should not.
    561   EXPECT_EQ(gfx::Point(20 + 50 + 350, 20 + dy).ToString(),
    562             child->GetBoundsInScreen().origin().ToString());
    563   EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
    564 
    565   DragStart(window.get());
    566   DragMove(0, -100);
    567   // While moving the windows should be in the panel container.
    568   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    569   EXPECT_EQ(kShellWindowId_PanelContainer, child->parent()->id());
    570   DragEnd();
    571   // When dropped they should return to the default container.
    572   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    573   EXPECT_EQ(kShellWindowId_DefaultContainer, child->parent()->id());
    574 
    575   // While moving the window and child should be moved to the panel container.
    576   DragStart(window.get());
    577   DragMove(20, 0);
    578   EXPECT_EQ(kShellWindowId_PanelContainer, window->parent()->id());
    579   EXPECT_EQ(kShellWindowId_PanelContainer, child->parent()->id());
    580   DragEnd();
    581 
    582   // When dropped they should return to the default container.
    583   EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
    584   EXPECT_EQ(kShellWindowId_DefaultContainer, child->parent()->id());
    585 }
    586 
    587 INSTANTIATE_TEST_CASE_P(LtrRtl, PanelWindowResizerTextDirectionTest,
    588                         testing::Bool());
    589 INSTANTIATE_TEST_CASE_P(NormalPanelPopup,
    590                         PanelWindowResizerTransientTest,
    591                         testing::Values(ui::wm::WINDOW_TYPE_NORMAL,
    592                                         ui::wm::WINDOW_TYPE_PANEL,
    593                                         ui::wm::WINDOW_TYPE_POPUP));
    594 
    595 }  // namespace ash
    596