Home | History | Annotate | Download | only in workspace
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ash/wm/workspace/workspace_window_resizer.h"
      6 
      7 #include "ash/ash_constants.h"
      8 #include "ash/ash_switches.h"
      9 #include "ash/display/display_controller.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/shell.h"
     14 #include "ash/shell_window_ids.h"
     15 #include "ash/test/ash_test_base.h"
     16 #include "ash/wm/property_util.h"
     17 #include "ash/wm/window_util.h"
     18 #include "ash/wm/workspace/phantom_window_controller.h"
     19 #include "ash/wm/workspace/snap_sizer.h"
     20 #include "ash/wm/workspace_controller.h"
     21 #include "base/command_line.h"
     22 #include "base/strings/string_number_conversions.h"
     23 #include "base/strings/stringprintf.h"
     24 #include "ui/aura/client/aura_constants.h"
     25 #include "ui/aura/root_window.h"
     26 #include "ui/aura/test/event_generator.h"
     27 #include "ui/aura/test/test_window_delegate.h"
     28 #include "ui/base/hit_test.h"
     29 #include "ui/gfx/insets.h"
     30 #include "ui/gfx/screen.h"
     31 #include "ui/views/widget/widget.h"
     32 
     33 namespace ash {
     34 namespace internal {
     35 namespace {
     36 
     37 const int kRootHeight = 600;
     38 
     39 // A simple window delegate that returns the specified min size.
     40 class TestWindowDelegate : public aura::test::TestWindowDelegate {
     41  public:
     42   TestWindowDelegate() {
     43   }
     44   virtual ~TestWindowDelegate() {}
     45 
     46   void set_min_size(const gfx::Size& size) {
     47     min_size_ = size;
     48   }
     49 
     50   void set_max_size(const gfx::Size& size) {
     51     max_size_ = size;
     52   }
     53 
     54  private:
     55   // Overridden from aura::Test::TestWindowDelegate:
     56   virtual gfx::Size GetMinimumSize() const OVERRIDE {
     57     return min_size_;
     58   }
     59 
     60   virtual gfx::Size GetMaximumSize() const OVERRIDE {
     61     return max_size_;
     62   }
     63 
     64   gfx::Size min_size_;
     65   gfx::Size max_size_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
     68 };
     69 
     70 class WorkspaceWindowResizerTest : public test::AshTestBase {
     71  public:
     72   WorkspaceWindowResizerTest() {}
     73   virtual ~WorkspaceWindowResizerTest() {}
     74 
     75   virtual void SetUp() OVERRIDE {
     76     AshTestBase::SetUp();
     77     UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
     78 
     79     aura::RootWindow* root = Shell::GetPrimaryRootWindow();
     80     gfx::Rect root_bounds(root->bounds());
     81 #if defined(OS_WIN)
     82     // RootWindow and Display can't resize on Windows Ash.
     83     // http://crbug.com/165962
     84     EXPECT_EQ(kRootHeight, root_bounds.height());
     85 #endif
     86     EXPECT_EQ(800, root_bounds.width());
     87     Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
     88     window_.reset(new aura::Window(&delegate_));
     89     window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
     90     window_->Init(ui::LAYER_NOT_DRAWN);
     91     SetDefaultParentByPrimaryRootWindow(window_.get());
     92     window_->set_id(1);
     93 
     94     window2_.reset(new aura::Window(&delegate2_));
     95     window2_->SetType(aura::client::WINDOW_TYPE_NORMAL);
     96     window2_->Init(ui::LAYER_NOT_DRAWN);
     97     SetDefaultParentByPrimaryRootWindow(window2_.get());
     98     window2_->set_id(2);
     99 
    100     window3_.reset(new aura::Window(&delegate3_));
    101     window3_->SetType(aura::client::WINDOW_TYPE_NORMAL);
    102     window3_->Init(ui::LAYER_NOT_DRAWN);
    103     SetDefaultParentByPrimaryRootWindow(window3_.get());
    104     window3_->set_id(3);
    105 
    106     window4_.reset(new aura::Window(&delegate4_));
    107     window4_->SetType(aura::client::WINDOW_TYPE_NORMAL);
    108     window4_->Init(ui::LAYER_NOT_DRAWN);
    109     SetDefaultParentByPrimaryRootWindow(window4_.get());
    110     window4_->set_id(4);
    111   }
    112 
    113   virtual void TearDown() OVERRIDE {
    114     window_.reset();
    115     window2_.reset();
    116     window3_.reset();
    117     window4_.reset();
    118     touch_resize_window_.reset();
    119     AshTestBase::TearDown();
    120   }
    121 
    122   // Returns a string identifying the z-order of each of the known child windows
    123   // of |parent|.  The returned string constains the id of the known windows and
    124   // is ordered from topmost to bottomost windows.
    125   std::string WindowOrderAsString(aura::Window* parent) const {
    126     std::string result;
    127     const aura::Window::Windows& windows = parent->children();
    128     for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin();
    129          i != windows.rend(); ++i) {
    130       if (*i == window_ || *i == window2_ || *i == window3_) {
    131         if (!result.empty())
    132           result += " ";
    133         result += base::IntToString((*i)->id());
    134       }
    135     }
    136     return result;
    137   }
    138 
    139  protected:
    140   gfx::Point CalculateDragPoint(const WorkspaceWindowResizer& resizer,
    141                                 int delta_x,
    142                                 int delta_y) const {
    143     gfx::Point location = resizer.GetInitialLocation();
    144     location.set_x(location.x() + delta_x);
    145     location.set_y(location.y() + delta_y);
    146     return location;
    147   }
    148 
    149   std::vector<aura::Window*> empty_windows() const {
    150     return std::vector<aura::Window*>();
    151   }
    152 
    153   internal::ShelfLayoutManager* shelf_layout_manager() {
    154     return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
    155   }
    156 
    157   void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) {
    158     touch_resize_delegate_.set_window_component(window_component);
    159     touch_resize_window_.reset(
    160         CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0,
    161                                             bounds));
    162     gfx::Insets mouse_insets = gfx::Insets(-ash::kResizeOutsideBoundsSize,
    163                                            -ash::kResizeOutsideBoundsSize,
    164                                            -ash::kResizeOutsideBoundsSize,
    165                                            -ash::kResizeOutsideBoundsSize);
    166     gfx::Insets touch_insets = mouse_insets.Scale(
    167         ash::kResizeOutsideBoundsScaleForTouch);
    168     touch_resize_window_->SetHitTestBoundsOverrideOuter(mouse_insets,
    169                                                         touch_insets);
    170     touch_resize_window_->set_hit_test_bounds_override_inner(mouse_insets);
    171   }
    172 
    173   TestWindowDelegate delegate_;
    174   TestWindowDelegate delegate2_;
    175   TestWindowDelegate delegate3_;
    176   TestWindowDelegate delegate4_;
    177   scoped_ptr<aura::Window> window_;
    178   scoped_ptr<aura::Window> window2_;
    179   scoped_ptr<aura::Window> window3_;
    180   scoped_ptr<aura::Window> window4_;
    181 
    182   TestWindowDelegate touch_resize_delegate_;
    183   scoped_ptr<aura::Window> touch_resize_window_;
    184 
    185  private:
    186   DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest);
    187 };
    188 
    189 class WorkspaceWindowResizerTestSticky : public WorkspaceWindowResizerTest {
    190  public:
    191   WorkspaceWindowResizerTestSticky() {}
    192   virtual ~WorkspaceWindowResizerTestSticky() {}
    193 
    194   virtual void SetUp() OVERRIDE {
    195     CommandLine::ForCurrentProcess()->AppendSwitch(
    196         ash::switches::kAshEnableStickyEdges);
    197     WorkspaceWindowResizerTest::SetUp();
    198   }
    199 
    200  private:
    201   DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTestSticky);
    202 };
    203 
    204 }  // namespace
    205 
    206 // Assertions around attached window resize dragging from the right with 2
    207 // windows.
    208 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) {
    209   window_->SetBounds(gfx::Rect(0, 300, 400, 300));
    210   window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
    211 
    212   std::vector<aura::Window*> windows;
    213   windows.push_back(window2_.get());
    214   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    215       window_.get(), gfx::Point(), HTRIGHT,
    216       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    217   ASSERT_TRUE(resizer.get());
    218   // Move it 100 to the right, which should expand w1 and push w2.
    219   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
    220   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
    221   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
    222 
    223   // Push off the screen, w2 should be resized to its min.
    224   delegate2_.set_min_size(gfx::Size(20, 20));
    225   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
    226   EXPECT_EQ("0,300 780x300", window_->bounds().ToString());
    227   EXPECT_EQ("780,200 20x200", window2_->bounds().ToString());
    228 
    229   // Move back to 100 and verify w2 gets its original size.
    230   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
    231   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
    232   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
    233 
    234   // Revert and make sure everything moves back.
    235   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
    236   resizer->RevertDrag();
    237   EXPECT_EQ("0,300 400x300", window_->bounds().ToString());
    238   EXPECT_EQ("400,200 100x200", window2_->bounds().ToString());
    239 }
    240 
    241 // Assertions around collapsing and expanding.
    242 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) {
    243   window_->SetBounds(gfx::Rect(   0, 300, 400, 300));
    244   window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
    245 
    246   std::vector<aura::Window*> windows;
    247   windows.push_back(window2_.get());
    248   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    249       window_.get(), gfx::Point(), HTRIGHT,
    250       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    251   ASSERT_TRUE(resizer.get());
    252   // Move it 100 to the left, which should expand w2 and collapse w1.
    253   resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0);
    254   EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
    255   EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
    256 
    257   // Collapse all the way to w1's min.
    258   delegate_.set_min_size(gfx::Size(20, 20));
    259   resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0);
    260   EXPECT_EQ("0,300 20x300", window_->bounds().ToString());
    261   EXPECT_EQ("20,200 480x200", window2_->bounds().ToString());
    262 
    263   // Move 100 to the left.
    264   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
    265   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
    266   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
    267 
    268   // Back to -100.
    269   resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0);
    270   EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
    271   EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
    272 }
    273 
    274 // Assertions around attached window resize dragging from the right with 3
    275 // windows.
    276 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) {
    277   window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
    278   window2_->SetBounds(gfx::Rect(300, 300, 150, 200));
    279   window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
    280   delegate2_.set_min_size(gfx::Size(52, 50));
    281   delegate3_.set_min_size(gfx::Size(38, 50));
    282 
    283   std::vector<aura::Window*> windows;
    284   windows.push_back(window2_.get());
    285   windows.push_back(window3_.get());
    286   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    287       window_.get(), gfx::Point(), HTRIGHT,
    288       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    289   ASSERT_TRUE(resizer.get());
    290   // Move it 100 to the right, which should expand w1 and push w2 and w3.
    291   resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
    292   EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
    293   EXPECT_EQ("400,300 150x200", window2_->bounds().ToString());
    294   EXPECT_EQ("550,300 100x200", window3_->bounds().ToString());
    295 
    296   // Move it 300, things should compress.
    297   resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0);
    298   EXPECT_EQ("100,300 500x300", window_->bounds().ToString());
    299   EXPECT_EQ("600,300 120x200", window2_->bounds().ToString());
    300   EXPECT_EQ("720,300 80x200", window3_->bounds().ToString());
    301 
    302   // Move it so much the last two end up at their min.
    303   resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0);
    304   EXPECT_EQ("100,300 610x300", window_->bounds().ToString());
    305   EXPECT_EQ("710,300 52x200", window2_->bounds().ToString());
    306   EXPECT_EQ("762,300 38x200", window3_->bounds().ToString());
    307 
    308   // Revert and make sure everything moves back.
    309   resizer->RevertDrag();
    310   EXPECT_EQ("100,300 200x300", window_->bounds().ToString());
    311   EXPECT_EQ("300,300 150x200", window2_->bounds().ToString());
    312   EXPECT_EQ("450,300 100x200", window3_->bounds().ToString());
    313 }
    314 
    315 // Assertions around attached window resizing (collapsing and expanding) with
    316 // 3 windows.
    317 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) {
    318   window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
    319   window2_->SetBounds(gfx::Rect(300, 300, 200, 200));
    320   window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
    321   delegate2_.set_min_size(gfx::Size(52, 50));
    322   delegate3_.set_min_size(gfx::Size(38, 50));
    323 
    324   std::vector<aura::Window*> windows;
    325   windows.push_back(window2_.get());
    326   windows.push_back(window3_.get());
    327   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    328       window_.get(), gfx::Point(), HTRIGHT,
    329       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    330   ASSERT_TRUE(resizer.get());
    331   // Move it -100 to the right, which should collapse w1 and expand w2 and w3.
    332   resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
    333   EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
    334   EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
    335   EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
    336 
    337   // Move it 100 to the right.
    338   resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
    339   EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
    340   EXPECT_EQ("400,300 200x200", window2_->bounds().ToString());
    341   EXPECT_EQ("600,300 100x200", window3_->bounds().ToString());
    342 
    343   // 100 to the left again.
    344   resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
    345   EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
    346   EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
    347   EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
    348 }
    349 
    350 // Assertions around collapsing and expanding from the bottom.
    351 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) {
    352   window_->SetBounds(gfx::Rect(   0, 100, 400, 300));
    353   window2_->SetBounds(gfx::Rect(400, 400, 100, 200));
    354 
    355   std::vector<aura::Window*> windows;
    356   windows.push_back(window2_.get());
    357   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    358       window_.get(), gfx::Point(), HTBOTTOM,
    359       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    360   ASSERT_TRUE(resizer.get());
    361   // Move it up 100, which should expand w2 and collapse w1.
    362   resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0);
    363   EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
    364   EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
    365 
    366   // Collapse all the way to w1's min.
    367   delegate_.set_min_size(gfx::Size(20, 20));
    368   resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0);
    369   EXPECT_EQ("0,100 400x20", window_->bounds().ToString());
    370   EXPECT_EQ("400,120 100x480", window2_->bounds().ToString());
    371 
    372   // Move 100 down.
    373   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
    374   EXPECT_EQ("0,100 400x400", window_->bounds().ToString());
    375   EXPECT_EQ("400,500 100x100", window2_->bounds().ToString());
    376 
    377   // Back to -100.
    378   resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0);
    379   EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
    380   EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
    381 }
    382 
    383 // Assertions around attached window resize dragging from the bottom with 2
    384 // windows.
    385 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) {
    386   window_->SetBounds(gfx::Rect( 0,  50, 400, 200));
    387   window2_->SetBounds(gfx::Rect(0, 250, 200, 100));
    388 
    389   std::vector<aura::Window*> windows;
    390   windows.push_back(window2_.get());
    391   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    392       window_.get(), gfx::Point(), HTBOTTOM,
    393       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    394   ASSERT_TRUE(resizer.get());
    395   // Move it 100 to the bottom, which should expand w1 and push w2.
    396   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
    397   EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
    398   EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
    399 
    400   // Push off the screen, w2 should be resized to its min.
    401   delegate2_.set_min_size(gfx::Size(20, 20));
    402   resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0);
    403   EXPECT_EQ("0,50 400x530", window_->bounds().ToString());
    404   EXPECT_EQ("0,580 200x20", window2_->bounds().ToString());
    405 
    406   // Move back to 100 and verify w2 gets its original size.
    407   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
    408   EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
    409   EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
    410 
    411   // Revert and make sure everything moves back.
    412   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
    413   resizer->RevertDrag();
    414   EXPECT_EQ("0,50 400x200", window_->bounds().ToString());
    415   EXPECT_EQ("0,250 200x100", window2_->bounds().ToString());
    416 }
    417 
    418 #if defined(OS_WIN)
    419 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
    420 #define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3
    421 #else
    422 #define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3
    423 #endif
    424 
    425 // Assertions around attached window resize dragging from the bottom with 3
    426 // windows.
    427 TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) {
    428   UpdateDisplay("600x800");
    429   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
    430   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
    431 
    432   window_->SetBounds(gfx::Rect( 300, 100, 300, 200));
    433   window2_->SetBounds(gfx::Rect(300, 300, 200, 150));
    434   window3_->SetBounds(gfx::Rect(300, 450, 200, 100));
    435   delegate2_.set_min_size(gfx::Size(50, 52));
    436   delegate3_.set_min_size(gfx::Size(50, 38));
    437 
    438   std::vector<aura::Window*> windows;
    439   windows.push_back(window2_.get());
    440   windows.push_back(window3_.get());
    441   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    442       window_.get(), gfx::Point(), HTBOTTOM,
    443       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    444   ASSERT_TRUE(resizer.get());
    445   // Move it 100 down, which should expand w1 and push w2 and w3.
    446   resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0);
    447   EXPECT_EQ("300,100 300x300", window_->bounds().ToString());
    448   EXPECT_EQ("300,400 200x150", window2_->bounds().ToString());
    449   EXPECT_EQ("300,550 200x100", window3_->bounds().ToString());
    450 
    451   // Move it 296 things should compress.
    452   resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0);
    453   EXPECT_EQ("300,100 300x496", window_->bounds().ToString());
    454   EXPECT_EQ("300,596 200x123", window2_->bounds().ToString());
    455   EXPECT_EQ("300,719 200x81", window3_->bounds().ToString());
    456 
    457   // Move it so much everything ends up at its min.
    458   resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0);
    459   EXPECT_EQ("300,100 300x610", window_->bounds().ToString());
    460   EXPECT_EQ("300,710 200x52", window2_->bounds().ToString());
    461   EXPECT_EQ("300,762 200x38", window3_->bounds().ToString());
    462 
    463   // Revert and make sure everything moves back.
    464   resizer->RevertDrag();
    465   EXPECT_EQ("300,100 300x200", window_->bounds().ToString());
    466   EXPECT_EQ("300,300 200x150", window2_->bounds().ToString());
    467   EXPECT_EQ("300,450 200x100", window3_->bounds().ToString());
    468 }
    469 
    470 // Assertions around attached window resizing (collapsing and expanding) with
    471 // 3 windows.
    472 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) {
    473   window_->SetBounds(gfx::Rect(  0,   0, 200, 200));
    474   window2_->SetBounds(gfx::Rect(10, 200, 200, 200));
    475   window3_->SetBounds(gfx::Rect(20, 400, 100, 100));
    476   delegate2_.set_min_size(gfx::Size(52, 50));
    477   delegate3_.set_min_size(gfx::Size(38, 50));
    478 
    479   std::vector<aura::Window*> windows;
    480   windows.push_back(window2_.get());
    481   windows.push_back(window3_.get());
    482   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    483       window_.get(), gfx::Point(), HTBOTTOM,
    484       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    485   ASSERT_TRUE(resizer.get());
    486   // Move it 100 up, which should collapse w1 and expand w2 and w3.
    487   resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
    488   EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
    489   EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
    490   EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
    491 
    492   // Move it 100 down.
    493   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
    494   EXPECT_EQ("0,0 200x300", window_->bounds().ToString());
    495   EXPECT_EQ("10,300 200x200", window2_->bounds().ToString());
    496   EXPECT_EQ("20,500 100x100", window3_->bounds().ToString());
    497 
    498   // 100 up again.
    499   resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
    500   EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
    501   EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
    502   EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
    503 }
    504 
    505 
    506 // Assertions around dragging to the left/right edge of the screen.
    507 TEST_F(WorkspaceWindowResizerTest, Edge) {
    508   int bottom =
    509       ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
    510   window_->SetBounds(gfx::Rect(20, 30, 50, 60));
    511   {
    512     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    513         window_.get(), gfx::Point(), HTCAPTION,
    514         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    515     ASSERT_TRUE(resizer.get());
    516     resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0);
    517     resizer->CompleteDrag(0);
    518     EXPECT_EQ("0,0 720x" + base::IntToString(bottom),
    519               window_->bounds().ToString());
    520     ASSERT_TRUE(GetRestoreBoundsInScreen(window_.get()));
    521     EXPECT_EQ("20,30 50x60",
    522               GetRestoreBoundsInScreen(window_.get())->ToString());
    523   }
    524   // Try the same with the right side.
    525   {
    526     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    527         window_.get(), gfx::Point(), HTCAPTION,
    528         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    529     ASSERT_TRUE(resizer.get());
    530     resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
    531     resizer->CompleteDrag(0);
    532     EXPECT_EQ("80,0 720x" + base::IntToString(bottom),
    533               window_->bounds().ToString());
    534     ASSERT_TRUE(GetRestoreBoundsInScreen(window_.get()));
    535     EXPECT_EQ("20,30 50x60",
    536               GetRestoreBoundsInScreen(window_.get())->ToString());
    537   }
    538 
    539   // Test if the restore bounds is correct in multiple displays.
    540   ClearRestoreBounds(window_.get());
    541 
    542   if (!SupportsMultipleDisplays())
    543     return;
    544 
    545   UpdateDisplay("800x600,200x600");
    546   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
    547   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
    548   window_->SetBoundsInScreen(gfx::Rect(800, 10, 50, 60),
    549                              ScreenAsh::GetSecondaryDisplay());
    550   EXPECT_EQ(root_windows[1], window_->GetRootWindow());
    551   {
    552     bottom =
    553         ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
    554     EXPECT_EQ("800,10 50x60", window_->GetBoundsInScreen().ToString());
    555 
    556     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    557         window_.get(), gfx::Point(), HTCAPTION,
    558         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    559     ASSERT_TRUE(resizer.get());
    560 
    561     resizer->Drag(CalculateDragPoint(*resizer, 199, 00), 0);
    562     resizer->CompleteDrag(0);
    563     // With the resolution of 200x600 we will hit in this case the 50% screen
    564     // size setting.
    565     EXPECT_EQ("100,0 100x" + base::IntToString(bottom),
    566               window_->bounds().ToString());
    567     EXPECT_EQ("800,10 50x60",
    568               GetRestoreBoundsInScreen(window_.get())->ToString());
    569   }
    570 }
    571 
    572 // Check that non resizable windows will not get resized.
    573 TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) {
    574   window_->SetBounds(gfx::Rect(20, 30, 50, 60));
    575   window_->SetProperty(aura::client::kCanResizeKey, false);
    576 
    577   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    578       window_.get(), gfx::Point(), HTCAPTION,
    579       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    580   ASSERT_TRUE(resizer.get());
    581   resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0);
    582   resizer->CompleteDrag(0);
    583   EXPECT_EQ("0,30 50x60", window_->bounds().ToString());
    584 }
    585 
    586 TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
    587   if (!SupportsMultipleDisplays())
    588     return;
    589 
    590   UpdateDisplay("800x600,800x600");
    591   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
    592   ASSERT_EQ(2U, root_windows.size());
    593 
    594   window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
    595                              Shell::GetScreen()->GetPrimaryDisplay());
    596   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
    597   EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
    598   {
    599     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    600         window_.get(), gfx::Point(), HTCAPTION,
    601         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    602     ASSERT_TRUE(resizer.get());
    603     EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
    604 
    605     // The pointer is on the edge but not shared. The snap phantom window
    606     // controller should be non-NULL.
    607     resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0);
    608     EXPECT_TRUE(resizer->snap_phantom_window_controller_.get());
    609 
    610     // Move the cursor across the edge. Now the snap phantom window controller
    611     // should be canceled.
    612     resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
    613     EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
    614   }
    615 }
    616 
    617 // Verifies windows are correctly restacked when reordering multiple windows.
    618 TEST_F(WorkspaceWindowResizerTest, RestackAttached) {
    619   window_->SetBounds(gfx::Rect(   0, 0, 200, 300));
    620   window2_->SetBounds(gfx::Rect(200, 0, 100, 200));
    621   window3_->SetBounds(gfx::Rect(300, 0, 100, 100));
    622 
    623   {
    624     std::vector<aura::Window*> windows;
    625     windows.push_back(window2_.get());
    626     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    627         window_.get(), gfx::Point(), HTRIGHT,
    628         aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    629     ASSERT_TRUE(resizer.get());
    630     // Move it 100 to the right, which should expand w1 and push w2 and w3.
    631     resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
    632 
    633     // 2 should be topmost since it's initially the highest in the stack.
    634     EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent()));
    635   }
    636 
    637   {
    638     std::vector<aura::Window*> windows;
    639     windows.push_back(window3_.get());
    640     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    641         window2_.get(), gfx::Point(), HTRIGHT,
    642         aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    643     ASSERT_TRUE(resizer.get());
    644     // Move it 100 to the right, which should expand w1 and push w2 and w3.
    645     resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
    646 
    647     // 2 should be topmost since it's initially the highest in the stack.
    648     EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent()));
    649   }
    650 }
    651 
    652 // Makes sure we don't allow dragging below the work area.
    653 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) {
    654   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    655       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
    656 
    657   ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays());
    658 
    659   window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    660   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    661       window_.get(), gfx::Point(), HTCAPTION,
    662       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    663   ASSERT_TRUE(resizer.get());
    664   resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0);
    665   int expected_y =
    666       kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
    667   EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
    668             window_->bounds().ToString());
    669 }
    670 
    671 // Makes sure we don't allow dragging on the work area with multidisplay.
    672 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) {
    673   if (!SupportsMultipleDisplays())
    674     return;
    675 
    676   UpdateDisplay("800x600,800x600");
    677   ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
    678 
    679   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    680       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
    681 
    682   // Positions the secondary display at the bottom the primary display.
    683   Shell::GetInstance()->display_controller()->SetLayoutForCurrentDisplays(
    684       ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0));
    685 
    686   {
    687     window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    688     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    689         window_.get(), gfx::Point(), HTCAPTION,
    690         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    691     ASSERT_TRUE(resizer.get());
    692     resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
    693     int expected_y =
    694         kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
    695     // When the mouse cursor is in the primary display, the window cannot move
    696     // on non-work area with kMinOnscreenHeight margin.
    697     EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
    698               window_->bounds().ToString());
    699   }
    700 
    701   {
    702     window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    703     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    704         window_.get(), gfx::Point(), HTCAPTION,
    705         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    706     ASSERT_TRUE(resizer.get());
    707     resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0);
    708     // The window can move to the secondary display beyond non-work area of
    709     // the primary display.
    710     EXPECT_EQ("100,800 300x400", window_->bounds().ToString());
    711   }
    712 }
    713 
    714 // Makes sure we don't allow dragging off the top of the work area.
    715 TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) {
    716   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    717       Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0));
    718 
    719   window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    720   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    721       window_.get(), gfx::Point(), HTCAPTION,
    722       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    723   ASSERT_TRUE(resizer.get());
    724   resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0);
    725   EXPECT_EQ("100,10 300x400", window_->bounds().ToString());
    726 }
    727 
    728 TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) {
    729   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    730       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    731 
    732   window_->SetBounds(gfx::Rect(100, 200, 300, 380));
    733   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    734       window_.get(), gfx::Point(), HTTOP,
    735       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    736   ASSERT_TRUE(resizer.get());
    737   resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0);
    738   EXPECT_EQ("100,200 300x380", window_->bounds().ToString());
    739 }
    740 
    741 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) {
    742   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    743       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    744   int left = ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).x();
    745   int pixels_to_left_border = 50;
    746   int window_width = 300;
    747   int window_x = left - window_width + pixels_to_left_border;
    748   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
    749   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    750       window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT,
    751       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    752   ASSERT_TRUE(resizer.get());
    753   resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0);
    754   EXPECT_EQ(base::IntToString(window_x) + ",100 " +
    755             base::IntToString(kMinimumOnScreenArea - window_x) +
    756             "x380", window_->bounds().ToString());
    757 }
    758 
    759 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) {
    760   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    761       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    762   int right = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    763       window_.get()).right();
    764   int pixels_to_right_border = 50;
    765   int window_width = 300;
    766   int window_x = right - pixels_to_right_border;
    767   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
    768   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    769       window_.get(), gfx::Point(window_x, 0), HTLEFT,
    770       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    771   ASSERT_TRUE(resizer.get());
    772   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
    773   EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
    774             ",100 " +
    775             base::IntToString(window_width - pixels_to_right_border +
    776                               kMinimumOnScreenArea) +
    777             "x380", window_->bounds().ToString());
    778 }
    779 
    780 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) {
    781   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    782       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    783   int bottom = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    784       window_.get()).bottom();
    785   int delta_to_bottom = 50;
    786   int height = 380;
    787   window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height));
    788   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    789       window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP,
    790       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    791   ASSERT_TRUE(resizer.get());
    792   resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0);
    793   EXPECT_EQ("100," +
    794             base::IntToString(bottom - kMinimumOnScreenArea) +
    795             " 300x" +
    796             base::IntToString(height - (delta_to_bottom -
    797                                         kMinimumOnScreenArea)),
    798             window_->bounds().ToString());
    799 }
    800 
    801 // Verifies that 'outside' check of the resizer take into account the extended
    802 // desktop in case of repositions.
    803 TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) {
    804   // Only primary display.  Changes the window position to fit within the
    805   // display.
    806   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    807       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    808   int right = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    809       window_.get()).right();
    810   int pixels_to_right_border = 50;
    811   int window_width = 300;
    812   int window_x = right - pixels_to_right_border;
    813   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
    814   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    815       window_.get(), gfx::Point(window_x, 0), HTCAPTION,
    816       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    817   ASSERT_TRUE(resizer.get());
    818   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
    819   EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
    820             ",100 " +
    821             base::IntToString(window_width) +
    822             "x380", window_->bounds().ToString());
    823 
    824   if (!SupportsMultipleDisplays())
    825     return;
    826 
    827   // With secondary display.  Operation itself is same but doesn't change
    828   // the position because the window is still within the secondary display.
    829   UpdateDisplay("1000x600,600x400");
    830   Shell::GetInstance()->SetDisplayWorkAreaInsets(
    831       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
    832   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
    833   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
    834   EXPECT_EQ(base::IntToString(window_x + window_width) +
    835             ",100 " +
    836             base::IntToString(window_width) +
    837             "x380", window_->bounds().ToString());
    838 }
    839 
    840 // Verifies snapping to edges works.
    841 TEST_F(WorkspaceWindowResizerTest, SnapToEdge) {
    842   Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
    843       SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    844   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
    845   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    846       window_.get(), gfx::Point(), HTCAPTION,
    847       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    848   ASSERT_TRUE(resizer.get());
    849   // Move to an x-coordinate of 15, which should not snap.
    850   resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
    851   // An x-coordinate of 7 should snap.
    852   resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0);
    853   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
    854   // Move to -15, should still snap to 0.
    855   resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
    856   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
    857   // At -32 should move past snap points.
    858   resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0);
    859   EXPECT_EQ("-32,112 320x160", window_->bounds().ToString());
    860   resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0);
    861   EXPECT_EQ("-33,112 320x160", window_->bounds().ToString());
    862 
    863   // Right side should similarly snap.
    864   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
    865   EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
    866   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0);
    867   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
    868   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
    869   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
    870   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0);
    871   EXPECT_EQ("512,112 320x160", window_->bounds().ToString());
    872   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0);
    873   EXPECT_EQ("513,112 320x160", window_->bounds().ToString());
    874 
    875   // And the bottom should snap too.
    876   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0);
    877   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
    878   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
    879   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
    880   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0);
    881   EXPECT_EQ("96,470 320x160", window_->bounds().ToString());
    882   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0);
    883   EXPECT_EQ("96,471 320x160", window_->bounds().ToString());
    884 
    885   // And the top should snap too.
    886   resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0);
    887   EXPECT_EQ("96,20 320x160", window_->bounds().ToString());
    888   resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0);
    889   EXPECT_EQ("96,0 320x160", window_->bounds().ToString());
    890   // No need to test dragging < 0 as we force that to 0.
    891 }
    892 
    893 // Verifies a resize snap when dragging TOPLEFT.
    894 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) {
    895   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
    896   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    897       window_.get(), gfx::Point(), HTTOPLEFT,
    898       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    899   ASSERT_TRUE(resizer.get());
    900   resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0);
    901   EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
    902 }
    903 
    904 // Verifies a resize snap when dragging TOPRIGHT.
    905 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) {
    906   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
    907   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    908                           window_.get()));
    909   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    910       window_.get(), gfx::Point(), HTTOPRIGHT,
    911       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    912   ASSERT_TRUE(resizer.get());
    913   resizer->Drag(
    914       CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0);
    915   EXPECT_EQ(100, window_->bounds().x());
    916   EXPECT_EQ(work_area.y(), window_->bounds().y());
    917   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
    918   EXPECT_EQ(230, window_->bounds().height());
    919 }
    920 
    921 // Verifies a resize snap when dragging BOTTOMRIGHT.
    922 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) {
    923   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
    924   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    925                           window_.get()));
    926   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    927       window_.get(), gfx::Point(), HTBOTTOMRIGHT,
    928       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    929   ASSERT_TRUE(resizer.get());
    930   resizer->Drag(
    931       CalculateDragPoint(*resizer, work_area.right() - 120 - 1,
    932                          work_area.bottom() - 220 - 2), 0);
    933   EXPECT_EQ(100, window_->bounds().x());
    934   EXPECT_EQ(200, window_->bounds().y());
    935   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
    936   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
    937 }
    938 
    939 // Verifies a resize snap when dragging BOTTOMLEFT.
    940 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) {
    941   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
    942   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
    943                           window_.get()));
    944   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    945       window_.get(), gfx::Point(), HTBOTTOMLEFT,
    946       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    947   ASSERT_TRUE(resizer.get());
    948   resizer->Drag(
    949       CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0);
    950   EXPECT_EQ(0, window_->bounds().x());
    951   EXPECT_EQ(200, window_->bounds().y());
    952   EXPECT_EQ(120, window_->bounds().width());
    953   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
    954 }
    955 
    956 // Verifies sticking to edges works.
    957 TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) {
    958   Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
    959       SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    960   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
    961   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
    962       window_.get(), gfx::Point(), HTCAPTION,
    963       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
    964   ASSERT_TRUE(resizer.get());
    965   // Move to an x-coordinate of 15, which should not stick.
    966   resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
    967   // Move to -15, should still stick to 0.
    968   resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
    969   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
    970   // At -100 should move past edge.
    971   resizer->Drag(CalculateDragPoint(*resizer, -100 - 96, 0), 0);
    972   EXPECT_EQ("-100,112 320x160", window_->bounds().ToString());
    973   resizer->Drag(CalculateDragPoint(*resizer, -101 - 96, 0), 0);
    974   EXPECT_EQ("-101,112 320x160", window_->bounds().ToString());
    975 
    976   // Right side should similarly stick.
    977   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
    978   EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
    979   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
    980   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
    981   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 100, 0), 0);
    982   EXPECT_EQ("580,112 320x160", window_->bounds().ToString());
    983   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 101, 0), 0);
    984   EXPECT_EQ("581,112 320x160", window_->bounds().ToString());
    985 
    986   // And the bottom should stick too.
    987   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
    988   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
    989   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 100), 0);
    990   EXPECT_EQ("96,538 320x160", window_->bounds().ToString());
    991   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 101), 0);
    992   EXPECT_EQ("96,539 320x160", window_->bounds().ToString());
    993 
    994   // No need to test dragging < 0 as we force that to 0.
    995 }
    996 
    997 // Verifies a resize sticks when dragging TOPLEFT.
    998 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPLEFT) {
    999   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1000   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1001       window_.get(), gfx::Point(), HTTOPLEFT,
   1002       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1003   ASSERT_TRUE(resizer.get());
   1004   resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, -15 -200), 0);
   1005   EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
   1006 }
   1007 
   1008 // Verifies a resize sticks when dragging TOPRIGHT.
   1009 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPRIGHT) {
   1010   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1011   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
   1012                           window_.get()));
   1013   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1014       window_.get(), gfx::Point(), HTTOPRIGHT,
   1015       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1016   ASSERT_TRUE(resizer.get());
   1017   resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 + 20,
   1018                                    -200 - 15), 0);
   1019   EXPECT_EQ(100, window_->bounds().x());
   1020   EXPECT_EQ(work_area.y(), window_->bounds().y());
   1021   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
   1022   EXPECT_EQ(230, window_->bounds().height());
   1023 }
   1024 
   1025 // Verifies a resize snap when dragging BOTTOMRIGHT.
   1026 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMRIGHT) {
   1027   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1028   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
   1029                           window_.get()));
   1030   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1031       window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1032       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1033   ASSERT_TRUE(resizer.get());
   1034   resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 - 20 + 15,
   1035                                    work_area.bottom() - 200 - 30 + 15), 0);
   1036   EXPECT_EQ(100, window_->bounds().x());
   1037   EXPECT_EQ(200, window_->bounds().y());
   1038   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
   1039   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
   1040 }
   1041 
   1042 // Verifies a resize snap when dragging BOTTOMLEFT.
   1043 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMLEFT) {
   1044   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1045   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
   1046                           window_.get()));
   1047   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1048       window_.get(), gfx::Point(), HTBOTTOMLEFT,
   1049       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1050   ASSERT_TRUE(resizer.get());
   1051   resizer->Drag(CalculateDragPoint(*resizer, -15 - 100,
   1052                                    work_area.bottom() - 200 - 30 + 15), 0);
   1053   EXPECT_EQ(0, window_->bounds().x());
   1054   EXPECT_EQ(200, window_->bounds().y());
   1055   EXPECT_EQ(120, window_->bounds().width());
   1056   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
   1057 }
   1058 
   1059 TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) {
   1060   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
   1061   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1062       window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1063       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1064   ASSERT_TRUE(resizer.get());
   1065   // Resize the right bottom to add 10 in width, 12 in height.
   1066   resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN);
   1067   // Both bottom and right sides to resize to exact size requested.
   1068   EXPECT_EQ("96,112 330x172", window_->bounds().ToString());
   1069 }
   1070 
   1071 TEST_F(WorkspaceWindowResizerTest, CtrlCompleteDragMoveToExactPosition) {
   1072   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
   1073   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1074       window_.get(), gfx::Point(), HTCAPTION,
   1075       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1076   ASSERT_TRUE(resizer.get());
   1077   // Ctrl + drag the window to new poistion by adding (10, 12) to its origin,
   1078   // the window should move to the exact position.
   1079   resizer->Drag(CalculateDragPoint(*resizer, 10, 12), 0);
   1080   resizer->CompleteDrag(ui::EF_CONTROL_DOWN);
   1081   EXPECT_EQ("106,124 320x160", window_->bounds().ToString());
   1082 }
   1083 
   1084 // Check that only usable sizes get returned by the resizer.
   1085 TEST_F(WorkspaceWindowResizerTest, TestProperSizerResolutions) {
   1086   // Check that we have the correct work area resolution which fits our
   1087   // expected test result.
   1088   gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
   1089                           window_.get()));
   1090   EXPECT_EQ(800, work_area.width());
   1091 
   1092   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
   1093   scoped_ptr<SnapSizer> resizer(new SnapSizer(
   1094       window_.get(),
   1095       gfx::Point(),
   1096       SnapSizer::LEFT_EDGE,
   1097       SnapSizer::OTHER_INPUT));
   1098   ASSERT_TRUE(resizer.get());
   1099   shelf_layout_manager()->SetAutoHideBehavior(
   1100       SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1101 
   1102   // Check that the list is declining and contains elements of the
   1103   // ideal size list [1280, 1024, 768, 640] as well as 50% and 90% the work
   1104   // area.
   1105   gfx::Rect rect = resizer->GetTargetBoundsForSize(0);
   1106   EXPECT_EQ("0,0 720x597", rect.ToString());
   1107   rect = resizer->GetTargetBoundsForSize(1);
   1108   EXPECT_EQ("0,0 640x597", rect.ToString());
   1109   rect = resizer->GetTargetBoundsForSize(2);
   1110   EXPECT_EQ("0,0 400x597", rect.ToString());
   1111   shelf_layout_manager()->SetAutoHideBehavior(
   1112       SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   1113   rect = resizer->GetTargetBoundsForSize(0);
   1114   EXPECT_EQ("0,0 720x552", rect.ToString());
   1115   rect = resizer->GetTargetBoundsForSize(1);
   1116   EXPECT_EQ("0,0 640x552", rect.ToString());
   1117   rect = resizer->GetTargetBoundsForSize(2);
   1118   EXPECT_EQ("0,0 400x552", rect.ToString());
   1119 }
   1120 
   1121 // Verifies that a dragged window will restore to its pre-maximized size.
   1122 TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) {
   1123   window_->SetBounds(gfx::Rect(0, 0, 1000, 1000));
   1124   SetRestoreBoundsInScreen(window_.get(), gfx::Rect(96, 112, 320, 160));
   1125   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1126       window_.get(), gfx::Point(), HTCAPTION,
   1127       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1128   ASSERT_TRUE(resizer.get());
   1129   // Drag the window to new position by adding (10, 10) to original point,
   1130   // the window should get restored.
   1131   resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
   1132   resizer->CompleteDrag(0);
   1133   EXPECT_EQ("10,10 320x160", window_->bounds().ToString());
   1134   // The restore rectangle should get cleared as well.
   1135   EXPECT_EQ(NULL, GetRestoreBoundsInScreen(window_.get()));
   1136 }
   1137 
   1138 // Verifies that a dragged window will restore to its pre-maximized size.
   1139 TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) {
   1140   const gfx::Rect initial_bounds(0, 0, 200, 400);
   1141   window_->SetBounds(initial_bounds);
   1142   SetRestoreBoundsInScreen(window_.get(), gfx::Rect(96, 112, 320, 160));
   1143   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1144       window_.get(), gfx::Point(), HTCAPTION,
   1145       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1146   ASSERT_TRUE(resizer.get());
   1147   // Drag the window to new poistion by adding (180, 16) to original point,
   1148   // the window should get restored.
   1149   resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0);
   1150   resizer->RevertDrag();
   1151   EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString());
   1152   EXPECT_EQ("96,112 320x160",
   1153       GetRestoreBoundsInScreen(window_.get())->ToString());
   1154 }
   1155 
   1156 // Check that only usable sizes get returned by the resizer.
   1157 TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) {
   1158   window_->SetBounds(gfx::Rect(10, 10, 20, 30));
   1159   window2_->SetBounds(gfx::Rect(150, 160, 25, 20));
   1160   window2_->Show();
   1161 
   1162   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1163       window_.get(), gfx::Point(), HTCAPTION,
   1164       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1165   ASSERT_TRUE(resizer.get());
   1166   // Move |window| one pixel to the left of |window2|. Should snap to right and
   1167   // top.
   1168   resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
   1169   EXPECT_EQ("130,160 20x30", window_->bounds().ToString());
   1170 
   1171   // Move |window| one pixel to the right of |window2|. Should snap to left and
   1172   // top.
   1173   resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0);
   1174   EXPECT_EQ("175,160 20x30", window_->bounds().ToString());
   1175 
   1176   // Move |window| one pixel above |window2|. Should snap to top and left.
   1177   resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0);
   1178   EXPECT_EQ("150,130 20x30", window_->bounds().ToString());
   1179 
   1180   // Move |window| one pixel above the bottom of |window2|. Should snap to
   1181   // bottom and left.
   1182   resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0);
   1183   EXPECT_EQ("150,180 20x30", window_->bounds().ToString());
   1184 }
   1185 
   1186 // The following variants verify magnetic snapping during resize when dragging a
   1187 // particular edge.
   1188 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) {
   1189   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1190   window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
   1191   window2_->Show();
   1192 
   1193   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1194     window_.get(), gfx::Point(), HTTOP,
   1195     aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1196   ASSERT_TRUE(resizer.get());
   1197   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1198   EXPECT_EQ("100,199 20x31", window_->bounds().ToString());
   1199 }
   1200 
   1201 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) {
   1202   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1203   window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
   1204   window2_->Show();
   1205 
   1206   {
   1207     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1208         window_.get(), gfx::Point(), HTTOPLEFT,
   1209         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1210     ASSERT_TRUE(resizer.get());
   1211     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1212     EXPECT_EQ("99,199 21x31", window_->bounds().ToString());
   1213     resizer->RevertDrag();
   1214   }
   1215 
   1216   {
   1217     window2_->SetBounds(gfx::Rect(88, 201, 10, 20));
   1218     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1219         window_.get(), gfx::Point(), HTTOPLEFT,
   1220         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1221     ASSERT_TRUE(resizer.get());
   1222     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1223     EXPECT_EQ("98,201 22x29", window_->bounds().ToString());
   1224     resizer->RevertDrag();
   1225   }
   1226 }
   1227 
   1228 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) {
   1229   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1230   window2_->Show();
   1231 
   1232   {
   1233     window2_->SetBounds(gfx::Rect(111, 179, 10, 20));
   1234     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1235         window_.get(), gfx::Point(), HTTOPRIGHT,
   1236         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1237     ASSERT_TRUE(resizer.get());
   1238     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1239     EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
   1240     resizer->RevertDrag();
   1241   }
   1242 
   1243   {
   1244     window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
   1245     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1246         window_.get(), gfx::Point(), HTTOPRIGHT,
   1247         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1248     ASSERT_TRUE(resizer.get());
   1249     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1250     EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
   1251     resizer->RevertDrag();
   1252   }
   1253 }
   1254 
   1255 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) {
   1256   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1257   window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
   1258   window2_->Show();
   1259 
   1260   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1261       window_.get(), gfx::Point(), HTRIGHT,
   1262       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1263   ASSERT_TRUE(resizer.get());
   1264   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1265   EXPECT_EQ("100,200 21x30", window_->bounds().ToString());
   1266 }
   1267 
   1268 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) {
   1269   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1270   window2_->Show();
   1271 
   1272   {
   1273     window2_->SetBounds(gfx::Rect(122, 212, 10, 20));
   1274     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1275         window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1276         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1277     ASSERT_TRUE(resizer.get());
   1278     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1279     EXPECT_EQ("100,200 22x32", window_->bounds().ToString());
   1280     resizer->RevertDrag();
   1281   }
   1282 
   1283   {
   1284     window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
   1285     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1286         window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1287         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1288     ASSERT_TRUE(resizer.get());
   1289     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1290     EXPECT_EQ("100,200 21x33", window_->bounds().ToString());
   1291     resizer->RevertDrag();
   1292   }
   1293 }
   1294 
   1295 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) {
   1296   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1297   window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
   1298   window2_->Show();
   1299 
   1300   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1301         window_.get(), gfx::Point(), HTBOTTOM,
   1302         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1303   ASSERT_TRUE(resizer.get());
   1304   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1305   EXPECT_EQ("100,200 20x33", window_->bounds().ToString());
   1306 }
   1307 
   1308 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) {
   1309   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1310   window2_->Show();
   1311 
   1312   {
   1313     window2_->SetBounds(gfx::Rect(99, 231, 10, 20));
   1314     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1315         window_.get(), gfx::Point(), HTBOTTOMLEFT,
   1316         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1317     ASSERT_TRUE(resizer.get());
   1318     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1319     EXPECT_EQ("99,200 21x31", window_->bounds().ToString());
   1320     resizer->RevertDrag();
   1321   }
   1322 
   1323   {
   1324     window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
   1325     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1326         window_.get(), gfx::Point(), HTBOTTOMLEFT,
   1327         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1328     ASSERT_TRUE(resizer.get());
   1329     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1330     EXPECT_EQ("99,200 21x29", window_->bounds().ToString());
   1331     resizer->RevertDrag();
   1332   }
   1333 }
   1334 
   1335 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
   1336   window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
   1337   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
   1338   window2_->Show();
   1339 
   1340   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1341       window_.get(), gfx::Point(), HTLEFT,
   1342       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1343   ASSERT_TRUE(resizer.get());
   1344   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
   1345   EXPECT_EQ("99,200 21x30", window_->bounds().ToString());
   1346 }
   1347 
   1348 // Test that the user user moved window flag is getting properly set.
   1349 TEST_F(WorkspaceWindowResizerTest, CheckUserWindowMangedFlags) {
   1350   window_->SetBounds(gfx::Rect( 0,  50, 400, 200));
   1351 
   1352   std::vector<aura::Window*> no_attached_windows;
   1353   // Check that an abort doesn't change anything.
   1354   {
   1355     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1356         window_.get(), gfx::Point(), HTCAPTION,
   1357         aura::client::WINDOW_MOVE_SOURCE_MOUSE, no_attached_windows));
   1358     ASSERT_TRUE(resizer.get());
   1359     // Move it 100 to the bottom.
   1360     resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
   1361     EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
   1362     resizer->RevertDrag();
   1363 
   1364     EXPECT_FALSE(ash::wm::HasUserChangedWindowPositionOrSize(window_.get()));
   1365   }
   1366 
   1367   // Check that a completed move / size does change the user coordinates.
   1368   {
   1369     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1370         window_.get(), gfx::Point(), HTCAPTION,
   1371         aura::client::WINDOW_MOVE_SOURCE_MOUSE, no_attached_windows));
   1372     ASSERT_TRUE(resizer.get());
   1373     // Move it 100 to the bottom.
   1374     resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
   1375     EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
   1376     resizer->CompleteDrag(0);
   1377     EXPECT_TRUE(ash::wm::HasUserChangedWindowPositionOrSize(window_.get()));
   1378   }
   1379 }
   1380 
   1381 // Test that a window with a specified max size doesn't exceed it when dragged.
   1382 TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) {
   1383   window_->SetBounds(gfx::Rect(0, 0, 400, 300));
   1384   delegate_.set_max_size(gfx::Size(401, 301));
   1385 
   1386   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1387       window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1388       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1389   resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
   1390   EXPECT_EQ(401, window_->bounds().width());
   1391   EXPECT_EQ(301, window_->bounds().height());
   1392 }
   1393 
   1394 // Test that a window with a specified max width doesn't restrict its height.
   1395 TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) {
   1396   window_->SetBounds(gfx::Rect(0, 0, 400, 300));
   1397   delegate_.set_max_size(gfx::Size(401, 0));
   1398 
   1399   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1400       window_.get(), gfx::Point(), HTBOTTOMRIGHT,
   1401       aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1402   resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
   1403   EXPECT_EQ(401, window_->bounds().width());
   1404   EXPECT_EQ(302, window_->bounds().height());
   1405 }
   1406 
   1407 // Test that a window with a specified max size can't be snapped.
   1408 TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) {
   1409   {
   1410     // With max size not set we get a phantom window controller for dragging off
   1411     // the right hand side.
   1412     window_->SetBounds(gfx::Rect(0, 0, 300, 200));
   1413 
   1414     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1415         window_.get(), gfx::Point(), HTCAPTION,
   1416         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1417     EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
   1418     resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
   1419     EXPECT_TRUE(resizer->snap_phantom_window_controller_.get());
   1420   }
   1421   {
   1422     // With max size defined, we get no phantom window.
   1423     window_->SetBounds(gfx::Rect(0, 0, 300, 200));
   1424     delegate_.set_max_size(gfx::Size(300, 200));
   1425 
   1426     scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1427         window_.get(), gfx::Point(), HTCAPTION,
   1428         aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
   1429     resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
   1430     EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
   1431   }
   1432 }
   1433 
   1434 TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) {
   1435   UpdateDisplay("600x800");
   1436   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1437   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1438 
   1439   // Four 100x100 windows flush against eachother, starting at 100,100.
   1440   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1441   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1442   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1443   window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
   1444   delegate2_.set_max_size(gfx::Size(101, 0));
   1445 
   1446   std::vector<aura::Window*> windows;
   1447   windows.push_back(window2_.get());
   1448   windows.push_back(window3_.get());
   1449   windows.push_back(window4_.get());
   1450   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1451       window_.get(), gfx::Point(), HTRIGHT,
   1452       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1453   ASSERT_TRUE(resizer.get());
   1454   // Move it 51 to the left, which should contract w1 and expand w2-4.
   1455   // w2 will hit its max size straight away, and in doing so will leave extra
   1456   // pixels that a naive implementation may award to the rightmost window. A
   1457   // fair implementation will give 25 pixels to each of the other windows.
   1458   resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
   1459   EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
   1460   EXPECT_EQ("149,100 101x100", window2_->bounds().ToString());
   1461   EXPECT_EQ("250,100 125x100", window3_->bounds().ToString());
   1462   EXPECT_EQ("375,100 125x100", window4_->bounds().ToString());
   1463 }
   1464 
   1465 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) {
   1466   UpdateDisplay("600x800");
   1467   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1468   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1469 
   1470   // Four 100x100 windows flush against eachother, starting at 100,100.
   1471   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1472   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1473   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1474   window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
   1475   delegate2_.set_max_size(gfx::Size(101, 0));
   1476   delegate3_.set_max_size(gfx::Size(101, 0));
   1477 
   1478   std::vector<aura::Window*> windows;
   1479   windows.push_back(window2_.get());
   1480   windows.push_back(window3_.get());
   1481   windows.push_back(window4_.get());
   1482   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1483       window_.get(), gfx::Point(), HTRIGHT,
   1484       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1485   ASSERT_TRUE(resizer.get());
   1486   // Move it 52 to the left, which should contract w1 and expand w2-4.
   1487   resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
   1488   EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
   1489   EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
   1490   EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
   1491   EXPECT_EQ("350,100 150x100", window4_->bounds().ToString());
   1492 }
   1493 
   1494 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) {
   1495   UpdateDisplay("600x800");
   1496   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1497   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1498 
   1499   // Four 100x100 windows flush against eachother, starting at 100,100.
   1500   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1501   window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
   1502   window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
   1503   window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
   1504   delegate2_.set_max_size(gfx::Size(0, 101));
   1505   delegate3_.set_max_size(gfx::Size(0, 101));
   1506 
   1507   std::vector<aura::Window*> windows;
   1508   windows.push_back(window2_.get());
   1509   windows.push_back(window3_.get());
   1510   windows.push_back(window4_.get());
   1511   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1512       window_.get(), gfx::Point(), HTBOTTOM,
   1513       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1514   ASSERT_TRUE(resizer.get());
   1515   // Move it 52 up, which should contract w1 and expand w2-4.
   1516   resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0);
   1517   EXPECT_EQ("100,100 100x48", window_->bounds().ToString());
   1518   EXPECT_EQ("100,148 100x101", window2_->bounds().ToString());
   1519   EXPECT_EQ("100,249 100x101", window3_->bounds().ToString());
   1520   EXPECT_EQ("100,350 100x150", window4_->bounds().ToString());
   1521 }
   1522 
   1523 #if defined(OS_WIN)
   1524 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
   1525 #define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight
   1526 #else
   1527 #define MAYBE_DontExceedMinHeight DontExceedMinHeight
   1528 #endif
   1529 
   1530 TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) {
   1531   UpdateDisplay("600x500");
   1532   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1533   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1534 
   1535   // Four 100x100 windows flush against eachother, starting at 100,100.
   1536   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1537   window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
   1538   window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
   1539   window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
   1540   delegate2_.set_min_size(gfx::Size(0, 99));
   1541   delegate3_.set_min_size(gfx::Size(0, 99));
   1542 
   1543   std::vector<aura::Window*> windows;
   1544   windows.push_back(window2_.get());
   1545   windows.push_back(window3_.get());
   1546   windows.push_back(window4_.get());
   1547   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1548       window_.get(), gfx::Point(), HTBOTTOM,
   1549       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1550   ASSERT_TRUE(resizer.get());
   1551   // Move it 52 down, which should expand w1 and contract w2-4.
   1552   resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0);
   1553   EXPECT_EQ("100,100 100x152", window_->bounds().ToString());
   1554   EXPECT_EQ("100,252 100x99", window2_->bounds().ToString());
   1555   EXPECT_EQ("100,351 100x99", window3_->bounds().ToString());
   1556   EXPECT_EQ("100,450 100x50", window4_->bounds().ToString());
   1557 }
   1558 
   1559 TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) {
   1560   UpdateDisplay("600x800");
   1561   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1562   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1563 
   1564   // Three 100x100 windows flush against eachother, starting at 100,100.
   1565   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1566   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1567   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1568   delegate3_.set_max_size(gfx::Size(101, 0));
   1569 
   1570   std::vector<aura::Window*> windows;
   1571   windows.push_back(window2_.get());
   1572   windows.push_back(window3_.get());
   1573   windows.push_back(window4_.get());
   1574   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1575       window_.get(), gfx::Point(), HTRIGHT,
   1576       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1577   ASSERT_TRUE(resizer.get());
   1578   // Move it 51 to the left, which should contract w1 and expand w2-3.
   1579   resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
   1580   EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
   1581   EXPECT_EQ("149,100 150x100", window2_->bounds().ToString());
   1582   EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
   1583 }
   1584 
   1585 TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) {
   1586   UpdateDisplay("600x800");
   1587   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1588   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1589 
   1590   // Three 100x100 windows flush against eachother, starting at 100,100.
   1591   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1592   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1593   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1594   delegate2_.set_max_size(gfx::Size(101, 0));
   1595   delegate3_.set_max_size(gfx::Size(101, 0));
   1596 
   1597   std::vector<aura::Window*> windows;
   1598   windows.push_back(window2_.get());
   1599   windows.push_back(window3_.get());
   1600   windows.push_back(window4_.get());
   1601   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1602       window_.get(), gfx::Point(), HTRIGHT,
   1603       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1604   ASSERT_TRUE(resizer.get());
   1605   // Move it 52 to the left, which should contract w1 and expand and move w2-3.
   1606   resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
   1607   EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
   1608   EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
   1609   EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
   1610 }
   1611 
   1612 #if defined(OS_WIN)
   1613 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
   1614 #define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth
   1615 #else
   1616 #define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth
   1617 #endif
   1618 
   1619 TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) {
   1620   UpdateDisplay("400x800");
   1621   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1622   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1623 
   1624   // Three 100x100 windows flush against eachother, starting at 100,100.
   1625   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1626   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1627   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1628   delegate_.set_max_size(gfx::Size(102, 0));
   1629 
   1630   std::vector<aura::Window*> windows;
   1631   windows.push_back(window2_.get());
   1632   windows.push_back(window3_.get());
   1633   windows.push_back(window4_.get());
   1634   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1635       window_.get(), gfx::Point(), HTRIGHT,
   1636       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1637   ASSERT_TRUE(resizer.get());
   1638   // Move it 50 to the right, which should expand w1 and contract w2-3, as they
   1639   // won't fit in the root window in their original sizes.
   1640   resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0);
   1641   EXPECT_EQ("100,100 102x100", window_->bounds().ToString());
   1642   EXPECT_EQ("202,100 99x100", window2_->bounds().ToString());
   1643   EXPECT_EQ("301,100 99x100", window3_->bounds().ToString());
   1644 }
   1645 
   1646 TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) {
   1647   UpdateDisplay("400x800");
   1648   aura::RootWindow* root = Shell::GetPrimaryRootWindow();
   1649   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
   1650 
   1651   // Three 100x100 windows flush against eachother, starting at 100,100.
   1652   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
   1653   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
   1654   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
   1655   delegate_.set_min_size(gfx::Size(98, 0));
   1656 
   1657   std::vector<aura::Window*> windows;
   1658   windows.push_back(window2_.get());
   1659   windows.push_back(window3_.get());
   1660   scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
   1661       window_.get(), gfx::Point(), HTRIGHT,
   1662       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
   1663   ASSERT_TRUE(resizer.get());
   1664   // Move it 50 to the left, which should contract w1 and expand w2-3.
   1665   resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0);
   1666   EXPECT_EQ("100,100 98x100", window_->bounds().ToString());
   1667   EXPECT_EQ("198,100 101x100", window2_->bounds().ToString());
   1668   EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
   1669 }
   1670 
   1671 // The following variants test that windows are resized correctly to the edges
   1672 // of the screen using touch, when touch point is off of the window border.
   1673 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) {
   1674   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
   1675 
   1676   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT);
   1677   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
   1678             touch_resize_window_->bounds().ToString());
   1679 
   1680   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
   1681                                        touch_resize_window_.get());
   1682 
   1683   // Drag out of the right border a bit and check if the border is aligned with
   1684   // the touch point.
   1685   generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2),
   1686                                   gfx::Point(725, kRootHeight / 2),
   1687                                   base::TimeDelta::FromMilliseconds(100),
   1688                                   1);
   1689   EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(),
   1690             touch_resize_window_->bounds().ToString());
   1691   // Drag more, but stop before being snapped to the edge.
   1692   generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2),
   1693                                   gfx::Point(760, kRootHeight / 2),
   1694                                   base::TimeDelta::FromMilliseconds(100),
   1695                                   1);
   1696   EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(),
   1697             touch_resize_window_->bounds().ToString());
   1698   // Drag even more to snap to the edge.
   1699   generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2),
   1700                                   gfx::Point(775, kRootHeight / 2),
   1701                                   base::TimeDelta::FromMilliseconds(100),
   1702                                   1);
   1703   EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(),
   1704             touch_resize_window_->bounds().ToString());
   1705 }
   1706 
   1707 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) {
   1708   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
   1709 
   1710   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT);
   1711   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
   1712             touch_resize_window_->bounds().ToString());
   1713 
   1714   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
   1715                                        touch_resize_window_.get());
   1716 
   1717   // Drag out of the left border a bit and check if the border is aligned with
   1718   // the touch point.
   1719   generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2),
   1720                                   gfx::Point(75, kRootHeight / 2),
   1721                                   base::TimeDelta::FromMilliseconds(100),
   1722                                   1);
   1723   EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(),
   1724             touch_resize_window_->bounds().ToString());
   1725   // Drag more, but stop before being snapped to the edge.
   1726   generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2),
   1727                                   gfx::Point(40, kRootHeight / 2),
   1728                                   base::TimeDelta::FromMilliseconds(100),
   1729                                   1);
   1730   EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(),
   1731             touch_resize_window_->bounds().ToString());
   1732   // Drag even more to snap to the edge.
   1733   generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2),
   1734                                   gfx::Point(25, kRootHeight / 2),
   1735                                   base::TimeDelta::FromMilliseconds(100),
   1736                                   1);
   1737   EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(),
   1738             touch_resize_window_->bounds().ToString());
   1739 }
   1740 
   1741 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) {
   1742   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
   1743 
   1744   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP);
   1745   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
   1746             touch_resize_window_->bounds().ToString());
   1747 
   1748   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
   1749                                        touch_resize_window_.get());
   1750 
   1751   // Drag out of the top border a bit and check if the border is aligned with
   1752   // the touch point.
   1753   generator.GestureScrollSequence(gfx::Point(400, 85),
   1754                                   gfx::Point(400, 75),
   1755                                   base::TimeDelta::FromMilliseconds(100),
   1756                                   1);
   1757   EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(),
   1758             touch_resize_window_->bounds().ToString());
   1759   // Drag more, but stop before being snapped to the edge.
   1760   generator.GestureScrollSequence(gfx::Point(400, 75),
   1761                                   gfx::Point(400, 40),
   1762                                   base::TimeDelta::FromMilliseconds(100),
   1763                                   1);
   1764   EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(),
   1765             touch_resize_window_->bounds().ToString());
   1766   // Drag even more to snap to the edge.
   1767   generator.GestureScrollSequence(gfx::Point(400, 40),
   1768                                   gfx::Point(400, 25),
   1769                                   base::TimeDelta::FromMilliseconds(100),
   1770                                   1);
   1771   EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(),
   1772             touch_resize_window_->bounds().ToString());
   1773 }
   1774 
   1775 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
   1776   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
   1777 
   1778   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM);
   1779   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
   1780             touch_resize_window_->bounds().ToString());
   1781 
   1782   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
   1783                                        touch_resize_window_.get());
   1784 
   1785   // Drag out of the bottom border a bit and check if the border is aligned with
   1786   // the touch point.
   1787   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85),
   1788                                   gfx::Point(400, kRootHeight - 75),
   1789                                   base::TimeDelta::FromMilliseconds(100),
   1790                                   1);
   1791   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(),
   1792             touch_resize_window_->bounds().ToString());
   1793   // Drag more, but stop before being snapped to the edge.
   1794   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75),
   1795                                   gfx::Point(400, kRootHeight - 40),
   1796                                   base::TimeDelta::FromMilliseconds(100),
   1797                                   1);
   1798   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(),
   1799             touch_resize_window_->bounds().ToString());
   1800   // Drag even more to snap to the edge.
   1801   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40),
   1802                                   gfx::Point(400, kRootHeight - 25),
   1803                                   base::TimeDelta::FromMilliseconds(100),
   1804                                   1);
   1805   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
   1806             touch_resize_window_->bounds().ToString());
   1807 }
   1808 }  // namespace internal
   1809 }  // namespace ash
   1810