text:
namespace ash {
namespace {

const int kRootHeight = 600;

// A simple window delegate that returns the specified min size.
class TestWindowDelegate : public aura::test::TestWindowDelegate {
 public:
  TestWindowDelegate() {
  }
  virtual ~TestWindowDelegate() {}

  void set_min_size(const gfx::Size& size) {
    min_size_ = size;
  }

  void set_max_size(const gfx::Size& size) {
    max_size_ = size;
  }

 private:
  // Overridden from aura::Test::TestWindowDelegate:
  virtual gfx::Size GetMinimumSize() const OVERRIDE {
    return min_size_;
  }

  virtual gfx::Size GetMaximumSize() const OVERRIDE {
    return max_size_;
  }

  gfx::Size min_size_;
  gfx::Size max_size_;

  DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
};

}  // namespace

class WorkspaceWindowResizerTest : public test::AshTestBase {
 public:
  WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {}
  virtual ~WorkspaceWindowResizerTest() {}

  virtual void SetUp() OVERRIDE {
    AshTestBase::SetUp();
    UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
    // Ignore the touch slop region.
    ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(0);

    aura::Window* root = Shell::GetPrimaryRootWindow();
    gfx::Rect root_bounds(root->bounds());
#if defined(OS_WIN)
    // RootWindow and Display can't resize on Windows Ash.
    // http://crbug.com/165962
    EXPECT_EQ(kRootHeight, root_bounds.height());
#endif
    EXPECT_EQ(800, root_bounds.width());
    Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
    window_.reset(new aura::Window(&delegate_));
    window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
    window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    ParentWindowInPrimaryRootWindow(window_.get());
    window_->set_id(1);

    window2_.reset(new aura::Window(&delegate2_));
    window2_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
    window2_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    ParentWindowInPrimaryRootWindow(window2_.get());
    window2_->set_id(2);

    window3_.reset(new aura::Window(&delegate3_));
    window3_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
    window3_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    ParentWindowInPrimaryRootWindow(window3_.get());
    window3_->set_id(3);

    window4_.reset(new aura::Window(&delegate4_));
    window4_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
    window4_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    ParentWindowInPrimaryRootWindow(window4_.get());
    window4_->set_id(4);
  }

  virtual void TearDown() OVERRIDE {
    window_.reset();
    window2_.reset();
    window3_.reset();
    window4_.reset();
    touch_resize_window_.reset();
    AshTestBase::TearDown();
  }

  // Returns a string identifying the z-order of each of the known child windows
  // of |parent|.  The returned string constains the id of the known windows and
  // is ordered from topmost to bottomost windows.
  std::string WindowOrderAsString(aura::Window* parent) const {
    std::string result;
    const aura::Window::Windows& windows = parent->children();
    for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin();
         i != windows.rend(); ++i) {
      if (*i == window_ || *i == window2_ || *i == window3_) {
        if (!result.empty())
          result += " ";
        result += base::IntToString((*i)->id());
      }
    }
    return result;
  }

 protected:
  WindowResizer* CreateResizerForTest(
      aura::Window* window,
      const gfx::Point& point_in_parent,
      int window_component) {
    WindowResizer* resizer = CreateWindowResizer(
        window,
        point_in_parent,
        window_component,
        aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
    workspace_resizer_ = WorkspaceWindowResizer::instance_;
    return resizer;
  }
  WorkspaceWindowResizer* CreateWorkspaceResizerForTest(
      aura::Window* window,
      const gfx::Point& point_in_parent,
      int window_component,
      aura::client::WindowMoveSource source,
      const std::vector<aura::Window*>& attached_windows) {
    wm::WindowState* window_state = wm::GetWindowState(window);
    window_state->CreateDragDetails(
        window, point_in_parent, window_component, source);
    return WorkspaceWindowResizer::Create(window_state, attached_windows);
  }

  PhantomWindowController* snap_phantom_window_controller() const {
    return workspace_resizer_->snap_phantom_window_controller_.get();
  }

  gfx::Point CalculateDragPoint(const WindowResizer& resizer,
                                int delta_x,
                                int delta_y) const {
    gfx::Point location = resizer.GetInitialLocation();
    location.set_x(location.x() + delta_x);
    location.set_y(location.y() + delta_y);
    return location;
  }

  std::vector<aura::Window*> empty_windows() const {
    return std::vector<aura::Window*>();
  }

  ShelfLayoutManager* shelf_layout_manager() {
    return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
  }

  void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) {
    touch_resize_delegate_.set_window_component(window_component);
    touch_resize_window_.reset(
        CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0,
                                            bounds));
  }

  TestWindowDelegate delegate_;
  TestWindowDelegate delegate2_;
  TestWindowDelegate delegate3_;
  TestWindowDelegate delegate4_;
  scoped_ptr<aura::Window> window_;
  scoped_ptr<aura::Window> window2_;
  scoped_ptr<aura::Window> window3_;
  scoped_ptr<aura::Window> window4_;

  TestWindowDelegate touch_resize_delegate_;
  scoped_ptr<aura::Window> touch_resize_window_;
  WorkspaceWindowResizer* workspace_resizer_;

 private:
  DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest);
};

// Assertions around attached window resize dragging from the right with 2
// windows.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) {
  window_->SetBounds(gfx::Rect(0, 300, 400, 300));
  window2_->SetBounds(gfx::Rect(400, 200, 100, 200));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 to the right, which should expand w1 and push w2.
  resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
  EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
  EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());

  // Push off the screen, w2 should be resized to its min.
  delegate2_.set_min_size(gfx::Size(20, 20));
  resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
  EXPECT_EQ("0,300 780x300", window_->bounds().ToString());
  EXPECT_EQ("780,200 20x200", window2_->bounds().ToString());

  // Move back to 100 and verify w2 gets its original size.
  resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
  EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
  EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());

  // Revert and make sure everything moves back.
  resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
  resizer->RevertDrag();
  EXPECT_EQ("0,300 400x300", window_->bounds().ToString());
  EXPECT_EQ("400,200 100x200", window2_->bounds().ToString());
}

// Assertions around collapsing and expanding.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) {
  window_->SetBounds(gfx::Rect(   0, 300, 400, 300));
  window2_->SetBounds(gfx::Rect(400, 200, 100, 200));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 to the left, which should expand w2 and collapse w1.
  resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0);
  EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
  EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());

  // Collapse all the way to w1's min.
  delegate_.set_min_size(gfx::Size(20, 20));
  resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0);
  EXPECT_EQ("0,300 20x300", window_->bounds().ToString());
  EXPECT_EQ("20,200 480x200", window2_->bounds().ToString());

  // Move 100 to the left.
  resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
  EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
  EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());

  // Back to -100.
  resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0);
  EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
  EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
}

// Assertions around attached window resize dragging from the right with 3
// windows.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) {
  window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
  window2_->SetBounds(gfx::Rect(300, 300, 150, 200));
  window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
  delegate2_.set_min_size(gfx::Size(52, 50));
  delegate3_.set_min_size(gfx::Size(38, 50));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 to the right, which should expand w1 and push w2 and w3.
  resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
  EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
  EXPECT_EQ("400,300 150x200", window2_->bounds().ToString());
  EXPECT_EQ("550,300 100x200", window3_->bounds().ToString());

  // Move it 300, things should compress.
  resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0);
  EXPECT_EQ("100,300 500x300", window_->bounds().ToString());
  EXPECT_EQ("600,300 120x200", window2_->bounds().ToString());
  EXPECT_EQ("720,300 80x200", window3_->bounds().ToString());

  // Move it so much the last two end up at their min.
  resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0);
  EXPECT_EQ("100,300 610x300", window_->bounds().ToString());
  EXPECT_EQ("710,300 52x200", window2_->bounds().ToString());
  EXPECT_EQ("762,300 38x200", window3_->bounds().ToString());

  // Revert and make sure everything moves back.
  resizer->RevertDrag();
  EXPECT_EQ("100,300 200x300", window_->bounds().ToString());
  EXPECT_EQ("300,300 150x200", window2_->bounds().ToString());
  EXPECT_EQ("450,300 100x200", window3_->bounds().ToString());
}

// Assertions around attached window resizing (collapsing and expanding) with
// 3 windows.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) {
  window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
  window2_->SetBounds(gfx::Rect(300, 300, 200, 200));
  window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
  delegate2_.set_min_size(gfx::Size(52, 50));
  delegate3_.set_min_size(gfx::Size(38, 50));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it -100 to the right, which should collapse w1 and expand w2 and w3.
  resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
  EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
  EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
  EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());

  // Move it 100 to the right.
  resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
  EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
  EXPECT_EQ("400,300 200x200", window2_->bounds().ToString());
  EXPECT_EQ("600,300 100x200", window3_->bounds().ToString());

  // 100 to the left again.
  resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
  EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
  EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
  EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
}

// Assertions around collapsing and expanding from the bottom.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) {
  window_->SetBounds(gfx::Rect(   0, 100, 400, 300));
  window2_->SetBounds(gfx::Rect(400, 400, 100, 200));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it up 100, which should expand w2 and collapse w1.
  resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0);
  EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
  EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());

  // Collapse all the way to w1's min.
  delegate_.set_min_size(gfx::Size(20, 20));
  resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0);
  EXPECT_EQ("0,100 400x20", window_->bounds().ToString());
  EXPECT_EQ("400,120 100x480", window2_->bounds().ToString());

  // Move 100 down.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
  EXPECT_EQ("0,100 400x400", window_->bounds().ToString());
  EXPECT_EQ("400,500 100x100", window2_->bounds().ToString());

  // Back to -100.
  resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0);
  EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
  EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
}

// Assertions around attached window resize dragging from the bottom with 2
// windows.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) {
  window_->SetBounds(gfx::Rect( 0,  50, 400, 200));
  window2_->SetBounds(gfx::Rect(0, 250, 200, 100));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 to the bottom, which should expand w1 and push w2.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
  EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
  EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());

  // Push off the screen, w2 should be resized to its min.
  delegate2_.set_min_size(gfx::Size(20, 20));
  resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0);
  EXPECT_EQ("0,50 400x530", window_->bounds().ToString());
  EXPECT_EQ("0,580 200x20", window2_->bounds().ToString());

  // Move back to 100 and verify w2 gets its original size.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
  EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
  EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());

  // Revert and make sure everything moves back.
  resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
  resizer->RevertDrag();
  EXPECT_EQ("0,50 400x200", window_->bounds().ToString());
  EXPECT_EQ("0,250 200x100", window2_->bounds().ToString());
}

#if defined(OS_WIN)
// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
#define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3
#else
#define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3
#endif

// Assertions around attached window resize dragging from the bottom with 3
// windows.
TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  window_->SetBounds(gfx::Rect( 300, 100, 300, 200));
  window2_->SetBounds(gfx::Rect(300, 300, 200, 150));
  window3_->SetBounds(gfx::Rect(300, 450, 200, 100));
  delegate2_.set_min_size(gfx::Size(50, 52));
  delegate3_.set_min_size(gfx::Size(50, 38));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 down, which should expand w1 and push w2 and w3.
  resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0);
  EXPECT_EQ("300,100 300x300", window_->bounds().ToString());
  EXPECT_EQ("300,400 200x150", window2_->bounds().ToString());
  EXPECT_EQ("300,550 200x100", window3_->bounds().ToString());

  // Move it 296 things should compress.
  resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0);
  EXPECT_EQ("300,100 300x496", window_->bounds().ToString());
  EXPECT_EQ("300,596 200x123", window2_->bounds().ToString());
  EXPECT_EQ("300,719 200x81", window3_->bounds().ToString());

  // Move it so much everything ends up at its min.
  resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0);
  EXPECT_EQ("300,100 300x610", window_->bounds().ToString());
  EXPECT_EQ("300,710 200x52", window2_->bounds().ToString());
  EXPECT_EQ("300,762 200x38", window3_->bounds().ToString());

  // Revert and make sure everything moves back.
  resizer->RevertDrag();
  EXPECT_EQ("300,100 300x200", window_->bounds().ToString());
  EXPECT_EQ("300,300 200x150", window2_->bounds().ToString());
  EXPECT_EQ("300,450 200x100", window3_->bounds().ToString());
}

// Assertions around attached window resizing (collapsing and expanding) with
// 3 windows.
TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) {
  window_->SetBounds(gfx::Rect(  0,   0, 200, 200));
  window2_->SetBounds(gfx::Rect(10, 200, 200, 200));
  window3_->SetBounds(gfx::Rect(20, 400, 100, 100));
  delegate2_.set_min_size(gfx::Size(52, 50));
  delegate3_.set_min_size(gfx::Size(38, 50));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 100 up, which should collapse w1 and expand w2 and w3.
  resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
  EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
  EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
  EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());

  // Move it 100 down.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
  EXPECT_EQ("0,0 200x300", window_->bounds().ToString());
  EXPECT_EQ("10,300 200x200", window2_->bounds().ToString());
  EXPECT_EQ("20,500 100x100", window3_->bounds().ToString());

  // 100 up again.
  resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
  EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
  EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
  EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
}

// Tests that touch-dragging a window does not lock the mouse cursor
// and therefore shows the cursor on a mousemove.
TEST_F(WorkspaceWindowResizerTest, MouseMoveWithTouchDrag) {
  window_->SetBounds(gfx::Rect(0, 300, 400, 300));
  window2_->SetBounds(gfx::Rect(400, 200, 100, 200));

  Shell* shell = Shell::GetInstance();
  aura::test::EventGenerator generator(window_->GetRootWindow());

  // The cursor should not be locked initially.
  EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_TOUCH, windows));
  ASSERT_TRUE(resizer.get());

  // Creating a WorkspaceWindowResizer should not lock the cursor.
  EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());

  // The cursor should be hidden after touching the screen and
  // starting a drag.
  EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
  generator.PressTouch();
  resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
  EXPECT_FALSE(shell->cursor_manager()->IsCursorVisible());
  EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());

  // Moving the mouse should show the cursor.
  generator.MoveMouseBy(1, 1);
  EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
  EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());

  resizer->RevertDrag();
}

// Assertions around dragging to the left/right edge of the screen.
TEST_F(WorkspaceWindowResizerTest, Edge) {
  if (!SupportsHostWindowResize())
    return;

  // Resize host window to force insets update.
  UpdateDisplay("800x700");
  // TODO(varkha): Insets are reset after every drag because of
  // http://crbug.com/292238.
  // Window is wide enough not to get docked right away.
  window_->SetBounds(gfx::Rect(20, 30, 400, 60));
  wm::WindowState* window_state = wm::GetWindowState(window_.get());

  {
    gfx::Rect expected_bounds_in_parent(
        wm::GetDefaultLeftSnappedWindowBoundsInParent(window_.get()));

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0);
    resizer->CompleteDrag();

    EXPECT_EQ(expected_bounds_in_parent.ToString(),
              window_->bounds().ToString());
    ASSERT_TRUE(window_state->HasRestoreBounds());
    EXPECT_EQ("20,30 400x60",
              window_state->GetRestoreBoundsInScreen().ToString());
  }
  // Try the same with the right side.
  {
    gfx::Rect expected_bounds_in_parent(
        wm::GetDefaultRightSnappedWindowBoundsInParent(window_.get()));

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
    resizer->CompleteDrag();
    EXPECT_EQ(expected_bounds_in_parent.ToString(),
              window_->bounds().ToString());
    ASSERT_TRUE(window_state->HasRestoreBounds());
    EXPECT_EQ("20,30 400x60",
              window_state->GetRestoreBoundsInScreen().ToString());
  }

  // Test if the restore bounds is correct in multiple displays.
  if (!SupportsMultipleDisplays())
    return;

  // Restore the window to clear snapped state.
  window_state->Restore();

  UpdateDisplay("800x600,500x600");
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  EXPECT_EQ(root_windows[0], window_->GetRootWindow());
  // Window is wide enough not to get docked right away.
  window_->SetBoundsInScreen(gfx::Rect(800, 10, 400, 60),
                             ScreenUtil::GetSecondaryDisplay());
  EXPECT_EQ(root_windows[1], window_->GetRootWindow());
  {
    EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString());

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0);
    int bottom =
        ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
    resizer->CompleteDrag();
    // With the resolution of 500x600 we will hit in this case the 50% screen
    // size setting.
    // TODO(varkha): Insets are updated because of http://crbug.com/292238
    EXPECT_EQ("250,0 250x" + base::IntToString(bottom),
              window_->bounds().ToString());
    EXPECT_EQ("800,10 400x60",
              window_state->GetRestoreBoundsInScreen().ToString());
  }
}

// Check that non resizable windows will not get resized.
TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) {
  window_->SetBounds(gfx::Rect(20, 30, 50, 60));
  window_->SetProperty(aura::client::kCanResizeKey, false);

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0);
  resizer->CompleteDrag();
  EXPECT_EQ("0,30 50x60", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
  if (!SupportsMultipleDisplays())
    return;

  UpdateDisplay("800x600,800x600");
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  ASSERT_EQ(2U, root_windows.size());

  window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
                             Shell::GetScreen()->GetPrimaryDisplay());
  EXPECT_EQ(root_windows[0], window_->GetRootWindow());
  EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
  {
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    EXPECT_FALSE(snap_phantom_window_controller());

    // The pointer is on the edge but not shared. The snap phantom window
    // controller should be non-NULL.
    resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0);
    EXPECT_TRUE(snap_phantom_window_controller());

    // Move the cursor across the edge. Now the snap phantom window controller
    // should be canceled.
    resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
    EXPECT_FALSE(snap_phantom_window_controller());
  }
}

// Verifies that dragging a snapped window unsnaps it.
TEST_F(WorkspaceWindowResizerTest, DragSnapped) {
  wm::WindowState* window_state = ash::wm::GetWindowState(window_.get());

  const gfx::Rect kInitialBounds(100, 100, 100, 100);
  window_->SetBounds(kInitialBounds);
  window_->Show();
  const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT);
  window_state->OnWMEvent(&snap_event);
  EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
  gfx::Rect snapped_bounds = window_->bounds();
  EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString());
  EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
            kInitialBounds.ToString());

  // Dragging a side snapped window should unsnap it.
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0);
  resizer->CompleteDrag();
  EXPECT_EQ(wm::WINDOW_STATE_TYPE_NORMAL, window_state->GetStateType());
  EXPECT_EQ("10,0 100x100", window_->bounds().ToString());
  EXPECT_FALSE(window_state->HasRestoreBounds());
}

// Verifies the behavior of resizing a side snapped window.
TEST_F(WorkspaceWindowResizerTest, ResizeSnapped) {
  wm::WindowState* window_state = ash::wm::GetWindowState(window_.get());

  const gfx::Rect kInitialBounds(100, 100, 100, 100);
  window_->SetBounds(kInitialBounds);
  window_->Show();

  const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT);
  window_state->OnWMEvent(&snap_event);
  EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
  gfx::Rect snapped_bounds = window_->bounds();
  EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString());
  EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
            kInitialBounds.ToString());

  {
    // 1) Resizing a side snapped window to make it wider should not unsnap the
    // window.
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTRIGHT));
    resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0);
    resizer->CompleteDrag();
    EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
    snapped_bounds.Inset(0, 0, -10, 0);
    EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString());
    EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
              kInitialBounds.ToString());
  }

  {
    // 2) Resizing a side snapped window vertically and then undoing the change
    // should not unsnap.
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOM));
    resizer->Drag(CalculateDragPoint(*resizer, 0, -30), 0);
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    resizer->CompleteDrag();
    EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
    EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString());
    EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
              kInitialBounds.ToString());
  }

  {
    // 3) Resizing a side snapped window vertically and then not undoing the
    // change should unsnap.
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOM));
    resizer->Drag(CalculateDragPoint(*resizer, 0, -10), 0);
    resizer->CompleteDrag();
    EXPECT_EQ(wm::WINDOW_STATE_TYPE_NORMAL, window_state->GetStateType());
    gfx::Rect expected_bounds(snapped_bounds);
    expected_bounds.Inset(0, 0, 0, 10);
    EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString());
    EXPECT_FALSE(window_state->HasRestoreBounds());
  }
}

// Verifies windows are correctly restacked when reordering multiple windows.
TEST_F(WorkspaceWindowResizerTest, RestackAttached) {
  window_->SetBounds(gfx::Rect(   0, 0, 200, 300));
  window2_->SetBounds(gfx::Rect(200, 0, 100, 200));
  window3_->SetBounds(gfx::Rect(300, 0, 100, 100));

  {
    std::vector<aura::Window*> windows;
    windows.push_back(window2_.get());
    scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
        window_.get(), gfx::Point(), HTRIGHT,
        aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    ASSERT_TRUE(resizer.get());
    // Move it 100 to the right, which should expand w1 and push w2 and w3.
    resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);

    // 2 should be topmost since it's initially the highest in the stack.
    EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent()));
  }

  {
    std::vector<aura::Window*> windows;
    windows.push_back(window3_.get());
    scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
        window2_.get(), gfx::Point(), HTRIGHT,
        aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
    ASSERT_TRUE(resizer.get());
    // Move it 100 to the right, which should expand w1 and push w2 and w3.
    resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);

    // 2 should be topmost since it's initially the highest in the stack.
    EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent()));
  }
}

// Makes sure we don't allow dragging below the work area.
TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));

  ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays());

  window_->SetBounds(gfx::Rect(100, 200, 300, 400));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0);
  int expected_y =
      kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
  EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
            window_->bounds().ToString());
}

// Makes sure we don't allow dragging on the work area with multidisplay.
TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) {
  if (!SupportsMultipleDisplays())
    return;

  UpdateDisplay("800x600,800x600");
  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());

  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));

  // Positions the secondary display at the bottom the primary display.
  Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
      ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0));

  {
    window_->SetBounds(gfx::Rect(100, 200, 300, 20));
    DCHECK_LT(window_->bounds().height(),
              WorkspaceWindowResizer::kMinOnscreenHeight);
    // Drag down avoiding dragging along the edge as that would side-snap.
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(10, 0), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
    int expected_y = kRootHeight - window_->bounds().height() - 10;
    // When the mouse cursor is in the primary display, the window cannot move
    // on non-work area but can get all the way towards the bottom,
    // restricted only by the window height.
    EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x20",
              window_->bounds().ToString());
    // Revert the drag in order to not remember the restore bounds.
    resizer->RevertDrag();
  }

  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
  {
    window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(10, 0), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    // Drag down avoiding dragging along the edge as that would side-snap.
    resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
    int expected_y =
        kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
    // When the mouse cursor is in the primary display, the window cannot move
    // on non-work area with kMinOnscreenHeight margin.
    EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
              window_->bounds().ToString());
    resizer->CompleteDrag();
  }

  {
    window_->SetBounds(gfx::Rect(100, 200, 300, 400));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), window_->bounds().origin(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    // Drag down avoiding getting stuck against the shelf on the bottom screen.
    resizer->Drag(CalculateDragPoint(*resizer, 0, 500), 0);
    // The window can move to the secondary display beyond non-work area of
    // the primary display.
    EXPECT_EQ("100,700 300x400", window_->bounds().ToString());
    resizer->CompleteDrag();
  }
}

// Makes sure we don't allow dragging off the top of the work area.
TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0));

  window_->SetBounds(gfx::Rect(100, 200, 300, 400));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0);
  EXPECT_EQ("100,10 300x400", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));

  window_->SetBounds(gfx::Rect(100, 200, 300, 380));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTTOP));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0);
  EXPECT_EQ("100,200 300x380", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
  int left = ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).x();
  int pixels_to_left_border = 50;
  int window_width = 300;
  int window_x = left - window_width + pixels_to_left_border;
  window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0);
  EXPECT_EQ(base::IntToString(window_x) + ",100 " +
            base::IntToString(kMinimumOnScreenArea - window_x) +
            "x380", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
  int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
      window_.get()).right();
  int pixels_to_right_border = 50;
  int window_width = 300;
  int window_x = right - pixels_to_right_border;
  window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(window_x, 0), HTLEFT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
  EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
            ",100 " +
            base::IntToString(window_width - pixels_to_right_border +
                              kMinimumOnScreenArea) +
            "x380", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) {
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
  int bottom = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
      window_.get()).bottom();
  int delta_to_bottom = 50;
  int height = 380;
  window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0);
  EXPECT_EQ("100," +
            base::IntToString(bottom - kMinimumOnScreenArea) +
            " 300x" +
            base::IntToString(height - (delta_to_bottom -
                                        kMinimumOnScreenArea)),
            window_->bounds().ToString());
}

// Verifies that 'outside' check of the resizer take into account the extended
// desktop in case of repositions.
TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) {
  // Only primary display.  Changes the window position to fit within the
  // display.
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
  int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
      window_.get()).right();
  int pixels_to_right_border = 50;
  int window_width = 300;
  int window_x = right - pixels_to_right_border;
  window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(window_x, 0), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
  EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
            ",100 " +
            base::IntToString(window_width) +
            "x380", window_->bounds().ToString());

  if (!SupportsMultipleDisplays())
    return;

  // With secondary display.  Operation itself is same but doesn't change
  // the position because the window is still within the secondary display.
  UpdateDisplay("1000x600,600x400");
  Shell::GetInstance()->SetDisplayWorkAreaInsets(
      Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
  window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
  resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
  EXPECT_EQ(base::IntToString(window_x + window_width) +
            ",100 " +
            base::IntToString(window_width) +
            "x380", window_->bounds().ToString());
}

// Verifies snapping to edges works.
TEST_F(WorkspaceWindowResizerTest, SnapToEdge) {
  Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
      SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
  window_->SetBounds(gfx::Rect(96, 112, 320, 160));
  // Click 50px to the right so that the mouse pointer does not leave the
  // workspace ensuring sticky behavior.
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(),
      window_->bounds().origin() + gfx::Vector2d(50, 0),
      HTCAPTION));
  ASSERT_TRUE(resizer.get());
  // Move to an x-coordinate of 15, which should not snap.
  resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
  // An x-coordinate of 7 should snap.
  resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0);
  EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
  // Move to -15, should still snap to 0.
  resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
  EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
  // At -32 should move past snap points.
  resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0);
  EXPECT_EQ("-32,112 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0);
  EXPECT_EQ("-33,112 320x160", window_->bounds().ToString());

  // Right side should similarly snap.
  resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
  EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0);
  EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
  EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0);
  EXPECT_EQ("512,112 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0);
  EXPECT_EQ("513,112 320x160", window_->bounds().ToString());

  // And the bottom should snap too.
  resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0);
  EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
  EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0);
  EXPECT_EQ("96,470 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0);
  EXPECT_EQ("96,471 320x160", window_->bounds().ToString());

  // And the top should snap too.
  resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0);
  EXPECT_EQ("96,20 320x160", window_->bounds().ToString());
  resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0);
  EXPECT_EQ("96,0 320x160", window_->bounds().ToString());

  // And bottom/left should snap too.
  resizer->Drag(
      CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0);
  EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
  resizer->Drag(
      CalculateDragPoint(*resizer, -15 - 96, 600 - 160 - 112 - 3 + 15), 0);
  EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
  // should move past snap points.
  resizer->Drag(
      CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0);
  EXPECT_EQ("-32,470 320x160", window_->bounds().ToString());
  resizer->Drag(
      CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0);
  EXPECT_EQ("-33,471 320x160", window_->bounds().ToString());

  // No need to test dragging < 0 as we force that to 0.
}

// Verifies a resize snap when dragging TOPLEFT.
TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTTOPLEFT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0);
  EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
}

// Verifies a resize snap when dragging TOPRIGHT.
TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
                          window_.get()));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTTOPRIGHT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(
      CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0);
  EXPECT_EQ(100, window_->bounds().x());
  EXPECT_EQ(work_area.y(), window_->bounds().y());
  EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
  EXPECT_EQ(230, window_->bounds().height());
}

// Verifies a resize snap when dragging BOTTOMRIGHT.
TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
                          window_.get()));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOMRIGHT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(
      CalculateDragPoint(*resizer, work_area.right() - 120 - 1,
                         work_area.bottom() - 220 - 2), 0);
  EXPECT_EQ(100, window_->bounds().x());
  EXPECT_EQ(200, window_->bounds().y());
  EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
  EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
}

// Verifies a resize snap when dragging BOTTOMLEFT.
TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
                          window_.get()));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOMLEFT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(
      CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0);
  EXPECT_EQ(0, window_->bounds().x());
  EXPECT_EQ(200, window_->bounds().y());
  EXPECT_EQ(120, window_->bounds().width());
  EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
}

// Verifies window sticks to both window and work area.
TEST_F(WorkspaceWindowResizerTest, StickToBothEdgeAndWindow) {
  window_->SetBounds(gfx::Rect(10, 10, 20, 50));
  window_->Show();
  window2_->SetBounds(gfx::Rect(150, 160, 25, 1000));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(10, 10), HTCAPTION));
  ASSERT_TRUE(resizer.get());

  // Move |window| one pixel to the left of |window2|. Should snap to right.
  resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
  gfx::Rect expected(130, 160, 20, 50);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());

  gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
                          window_.get()));

  // The initial y position of |window_|.
  int initial_y = 10;
  // The drag position where the window is exactly attached to the bottom.
  int attach_y = work_area.bottom() - window_->bounds().height() - initial_y;

  // Dragging 10px above should not attach to the bottom.
  resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y - 10), 0);
  expected.set_y(attach_y + initial_y - 10);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());

  // Stick to the work area.
  resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y - 1), 0);
  expected.set_y(attach_y + initial_y);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());

  resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y), 0);
  expected.set_y(attach_y + initial_y);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());

  resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y + 1), 0);
  expected.set_y(attach_y + initial_y);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());

  // Moving down further should move the window.
  resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y + 18), 0);
  expected.set_y(attach_y + initial_y + 18);
  EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) {
  window_->SetBounds(gfx::Rect(96, 112, 320, 160));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOMRIGHT));
  ASSERT_TRUE(resizer.get());
  // Resize the right bottom to add 10 in width, 12 in height.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN);
  // Both bottom and right sides to resize to exact size requested.
  EXPECT_EQ("96,112 330x172", window_->bounds().ToString());
}

// Verifies that a dragged window will restore to its pre-maximized size.
TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) {
  window_->SetBounds(gfx::Rect(0, 0, 1000, 1000));
  wm::WindowState* window_state = wm::GetWindowState(window_.get());
  window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  // Drag the window to new position by adding (10, 10) to original point,
  // the window should get restored.
  resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
  resizer->CompleteDrag();
  EXPECT_EQ("10,10 320x160", window_->bounds().ToString());
  // The restore rectangle should get cleared as well.
  EXPECT_FALSE(window_state->HasRestoreBounds());
}

// Verifies that a dragged window will restore to its pre-maximized size.
TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) {
  const gfx::Rect initial_bounds(0, 0, 200, 400);
  window_->SetBounds(initial_bounds);

  wm::WindowState* window_state = wm::GetWindowState(window_.get());
  window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  // Drag the window to new poistion by adding (180, 16) to original point,
  // the window should get restored.
  resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0);
  resizer->RevertDrag();
  EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString());
  EXPECT_EQ("96,112 320x160",
            window_state->GetRestoreBoundsInScreen().ToString());
}

// Check that only usable sizes get returned by the resizer.
TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) {
  window_->SetBounds(gfx::Rect(10, 10, 20, 30));
  window2_->SetBounds(gfx::Rect(150, 160, 25, 20));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTCAPTION));
  ASSERT_TRUE(resizer.get());
  // Move |window| one pixel to the left of |window2|. Should snap to right and
  // top.
  resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
  EXPECT_EQ("130,160 20x30", window_->bounds().ToString());

  // Move |window| one pixel to the right of |window2|. Should snap to left and
  // top.
  resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0);
  EXPECT_EQ("175,160 20x30", window_->bounds().ToString());

  // Move |window| one pixel above |window2|. Should snap to top and left.
  resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0);
  EXPECT_EQ("150,130 20x30", window_->bounds().ToString());

  // Move |window| one pixel above the bottom of |window2|. Should snap to
  // bottom and left.
  resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0);
  EXPECT_EQ("150,180 20x30", window_->bounds().ToString());
}

// The following variants verify magnetic snapping during resize when dragging a
// particular edge.
TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTTOP));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
  EXPECT_EQ("100,199 20x31", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
  window2_->Show();

  {
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTTOPLEFT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("99,199 21x31", window_->bounds().ToString());
    resizer->RevertDrag();
  }

  {
    window2_->SetBounds(gfx::Rect(88, 201, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTTOPLEFT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("98,201 22x29", window_->bounds().ToString());
    resizer->RevertDrag();
  }
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->Show();

  {
    window2_->SetBounds(gfx::Rect(111, 179, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTTOPRIGHT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
    resizer->RevertDrag();
  }

  {
    window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTTOPRIGHT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
    resizer->RevertDrag();
  }
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
  EXPECT_EQ("100,200 21x30", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->Show();

  {
    window2_->SetBounds(gfx::Rect(122, 212, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOMRIGHT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("100,200 22x32", window_->bounds().ToString());
    resizer->RevertDrag();
  }

  {
    window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOMRIGHT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("100,200 21x33", window_->bounds().ToString());
    resizer->RevertDrag();
  }
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
  EXPECT_EQ("100,200 20x33", window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) {
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->Show();

  {
    window2_->SetBounds(gfx::Rect(99, 231, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOMLEFT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("99,200 21x31", window_->bounds().ToString());
    resizer->RevertDrag();
  }

  {
    window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTBOTTOMLEFT));
    ASSERT_TRUE(resizer.get());
    resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
    EXPECT_EQ("99,200 21x29", window_->bounds().ToString());
    resizer->RevertDrag();
  }
}

TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
  window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
  window_->SetBounds(gfx::Rect(100, 200, 20, 30));
  window2_->Show();

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTLEFT));
  ASSERT_TRUE(resizer.get());
  resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
  EXPECT_EQ("99,200 21x30", window_->bounds().ToString());
}

// Test that the user user moved window flag is getting properly set.
TEST_F(WorkspaceWindowResizerTest, CheckUserWindowManagedFlags) {
  window_->SetBounds(gfx::Rect( 0,  50, 400, 200));

  std::vector<aura::Window*> no_attached_windows;
  // Check that an abort doesn't change anything.
  {
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    // Move it 100 to the bottom.
    resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
    EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
    resizer->RevertDrag();

    EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
  }

  // Check that a completed move / size does change the user coordinates.
  {
    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    ASSERT_TRUE(resizer.get());
    // Move it 100 to the bottom.
    resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
    EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
    resizer->CompleteDrag();
    EXPECT_TRUE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
  }
}

// Test that a window with a specified max size doesn't exceed it when dragged.
TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) {
  window_->SetBounds(gfx::Rect(0, 0, 400, 300));
  delegate_.set_max_size(gfx::Size(401, 301));

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOMRIGHT));
  resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
  EXPECT_EQ(401, window_->bounds().width());
  EXPECT_EQ(301, window_->bounds().height());
}

// Test that a window with a specified max width doesn't restrict its height.
TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) {
  window_->SetBounds(gfx::Rect(0, 0, 400, 300));
  delegate_.set_max_size(gfx::Size(401, 0));

  scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOMRIGHT));
  resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
  EXPECT_EQ(401, window_->bounds().width());
  EXPECT_EQ(302, window_->bounds().height());
}

// Test that a window with a specified max size can't be snapped.
TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) {
  {
    // With max size not set we get a phantom window controller for dragging off
    // the right hand side.
    // Make the window wider than maximum docked width.
    window_->SetBounds(gfx::Rect(0, 0, 400, 200));

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    EXPECT_FALSE(snap_phantom_window_controller());
    resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
    EXPECT_TRUE(snap_phantom_window_controller());
    resizer->RevertDrag();
  }
  {
    // With max size defined, we get no phantom window for snapping but we still
    // get a phantom window (docking guide).
    window_->SetBounds(gfx::Rect(0, 0, 400, 200));
    delegate_.set_max_size(gfx::Size(400, 200));

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
    EXPECT_TRUE(snap_phantom_window_controller());
    resizer->RevertDrag();
  }
  {
    // With max size defined, we get no phantom window for snapping.
    window_->SetBounds(gfx::Rect(0, 0, 400, 200));
    delegate_.set_max_size(gfx::Size(400, 200));
    // With min size defined, we get no phantom window for docking.
    delegate_.set_min_size(gfx::Size(400, 200));

    scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
        window_.get(), gfx::Point(), HTCAPTION));
    resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
    EXPECT_FALSE(snap_phantom_window_controller());
    resizer->RevertDrag();
  }
}

TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Four 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
  delegate2_.set_max_size(gfx::Size(101, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 51 to the left, which should contract w1 and expand w2-4.
  // w2 will hit its max size straight away, and in doing so will leave extra
  // pixels that a naive implementation may award to the rightmost window. A
  // fair implementation will give 25 pixels to each of the other windows.
  resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
  EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
  EXPECT_EQ("149,100 101x100", window2_->bounds().ToString());
  EXPECT_EQ("250,100 125x100", window3_->bounds().ToString());
  EXPECT_EQ("375,100 125x100", window4_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Four 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
  delegate2_.set_max_size(gfx::Size(101, 0));
  delegate3_.set_max_size(gfx::Size(101, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 52 to the left, which should contract w1 and expand w2-4.
  resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
  EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
  EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
  EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
  EXPECT_EQ("350,100 150x100", window4_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Four 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
  window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
  window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
  delegate2_.set_max_size(gfx::Size(0, 101));
  delegate3_.set_max_size(gfx::Size(0, 101));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 52 up, which should contract w1 and expand w2-4.
  resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0);
  EXPECT_EQ("100,100 100x48", window_->bounds().ToString());
  EXPECT_EQ("100,148 100x101", window2_->bounds().ToString());
  EXPECT_EQ("100,249 100x101", window3_->bounds().ToString());
  EXPECT_EQ("100,350 100x150", window4_->bounds().ToString());
}

#if defined(OS_WIN)
// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
#define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight
#else
#define MAYBE_DontExceedMinHeight DontExceedMinHeight
#endif

TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) {
  UpdateDisplay("600x500");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Four 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
  window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
  window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
  delegate2_.set_min_size(gfx::Size(0, 99));
  delegate3_.set_min_size(gfx::Size(0, 99));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTBOTTOM,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 52 down, which should expand w1 and contract w2-4.
  resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0);
  EXPECT_EQ("100,100 100x152", window_->bounds().ToString());
  EXPECT_EQ("100,252 100x99", window2_->bounds().ToString());
  EXPECT_EQ("100,351 100x99", window3_->bounds().ToString());
  EXPECT_EQ("100,450 100x50", window4_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Three 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  delegate3_.set_max_size(gfx::Size(101, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 51 to the left, which should contract w1 and expand w2-3.
  resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
  EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
  EXPECT_EQ("149,100 150x100", window2_->bounds().ToString());
  EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) {
  UpdateDisplay("600x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Three 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  delegate2_.set_max_size(gfx::Size(101, 0));
  delegate3_.set_max_size(gfx::Size(101, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 52 to the left, which should contract w1 and expand and move w2-3.
  resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
  EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
  EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
  EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
}

#if defined(OS_WIN)
// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
#define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth
#else
#define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth
#endif

TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) {
  UpdateDisplay("400x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Three 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  delegate_.set_max_size(gfx::Size(102, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  windows.push_back(window4_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 50 to the right, which should expand w1 and contract w2-3, as they
  // won't fit in the root window in their original sizes.
  resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0);
  EXPECT_EQ("100,100 102x100", window_->bounds().ToString());
  EXPECT_EQ("202,100 99x100", window2_->bounds().ToString());
  EXPECT_EQ("301,100 99x100", window3_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) {
  UpdateDisplay("400x800");
  aura::Window* root = Shell::GetPrimaryRootWindow();
  Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());

  // Three 100x100 windows flush against eachother, starting at 100,100.
  window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
  window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
  window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
  delegate_.set_min_size(gfx::Size(98, 0));

  std::vector<aura::Window*> windows;
  windows.push_back(window2_.get());
  windows.push_back(window3_.get());
  scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
      window_.get(), gfx::Point(), HTRIGHT,
      aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
  ASSERT_TRUE(resizer.get());
  // Move it 50 to the left, which should contract w1 and expand w2-3.
  resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0);
  EXPECT_EQ("100,100 98x100", window_->bounds().ToString());
  EXPECT_EQ("198,100 101x100", window2_->bounds().ToString());
  EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
}

// The following variants test that windows are resized correctly to the edges
// of the screen using touch, when touch point is off of the window border.
TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) {
  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);

  InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());

  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
                                       touch_resize_window_.get());

  // Drag out of the right border a bit and check if the border is aligned with
  // the touch point.
  generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2),
                                  gfx::Point(725, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag more, but stop before being snapped to the edge.
  generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2),
                                  gfx::Point(760, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag even more to snap to the edge.
  generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2),
                                  gfx::Point(775, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) {
  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);

  InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());

  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
                                       touch_resize_window_.get());

  // Drag out of the left border a bit and check if the border is aligned with
  // the touch point.
  generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2),
                                  gfx::Point(75, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag more, but stop before being snapped to the edge.
  generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2),
                                  gfx::Point(40, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag even more to snap to the edge.
  generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2),
                                  gfx::Point(25, kRootHeight / 2),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) {
  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);

  InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());

  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
                                       touch_resize_window_.get());

  // Drag out of the top border a bit and check if the border is aligned with
  // the touch point.
  generator.GestureScrollSequence(gfx::Point(400, 85),
                                  gfx::Point(400, 75),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag more, but stop before being snapped to the edge.
  generator.GestureScrollSequence(gfx::Point(400, 75),
                                  gfx::Point(400, 40),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag even more to snap to the edge.
  generator.GestureScrollSequence(gfx::Point(400, 40),
                                  gfx::Point(400, 25),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(),
            touch_resize_window_->bounds().ToString());
}

TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);

  InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
            touch_resize_window_->bounds().ToString());

  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
                                       touch_resize_window_.get());

  // Drag out of the bottom border a bit and check if the border is aligned with
  // the touch point.
  generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85),
                                  gfx::Point(400, kRootHeight - 75),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag more, but stop before being snapped to the edge.
  generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75),
                                  gfx::Point(400, kRootHeight - 40),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(),
            touch_resize_window_->bounds().ToString());
  // Drag even more to snap to the edge.
  generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40),
                                  gfx::Point(400, kRootHeight - 25),
                                  base::TimeDelta::FromMilliseconds(10),
                                  5);
  EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
            touch_resize_window_->bounds().ToString());
}

}  // namespace ash

redpajama_set_name: RedPajamaGithub


The perfect travel buddy for music on the go! The Boom Ball is one of the smallest stereo Bluetooth speakers around. It looks like a ball but flip open the wing speaker and create a portable stereo speaker.
Boom Ball fits into a jacket pocket or a small back so is perfect if you want music on your travels.


text:
Carriera
Cresciuto nell'Enotria Goliardo, ha esordito con il  nella Prima Categoria Lombarda il 9 ottobre 1921 nella partita Pavia-Esperia Como (1-0). Con i pavesi ha disputato due campionati, il primo nel 1921-1922 di Prima Categoria Lombarda con 4 presenze e 4 reti subite, il secondo nel 1922-1923 di Seconda Divisione con 9 presenze e 11 reti subite, per un totale di 14 presenze a difesa dalla porta e 15 reti al passivo. Ha giocato a Sesto San Giovanni nelle Acciaierie Falck la stagione 1927-1928.

Note

Collegamenti esterni
Scheda Almanaccocalciatori.blogspot.it

redpajama_set_name: RedPajamaWikipedia


Have you enjoyed your science and mathematics classes and thought they were interesting? Have you enjoyed your laboratory classes and discovered that you had a real talent for experimental science?
Have you ever thought about undergraduate research but thought you were not capable of research? Many students get the message that they are not capable of research. Not true! You just need a professor who will encourage undergraduate research!
Speak with your high school science teacher. He or she will be able to provide some valuable insight and might help you explore undergraduate research opportunities.
Contact the admissions staff at the member institutions and ask them about undergraduate research opportunities. When you visit the college/university ask to speak with professors about their research. Ask the professors about the projects they are currently working on. Even if you are not majoring in their department, professors would be happy to have you participate in undergraduate research. Some colleges/universities offer research opportunities in the freshman year! Ask when you can begin research projects.
When you speak with the professor ask about the variety of ways that you can join the research team. You can volunteer, be paid through work-study, or apply for course credit for research.
To learn more about research opportunities at a member institution, simply click the member institution's name. If there are questions, get in touch with the contact person listed on the chart.


text:
Call Us Today! 888-313-7916|advertising@egpublishing.com
Deer Valley Times
North Tatum Times
North 32nd News
Scottsdale North News
The Scottsdale Standard
Upper Westsider
Zerorez of Phoenix Expands to Deer Valley; Focused on Cleaning Up While Giving Back
Home/All Category, Business DVT, News DVT/Zerorez of Phoenix Expands to Deer Valley; Focused on Cleaning Up While Giving Back
One of the fastest growing and most successful cleaning businesses in Arizona got its start in – of all places – a garage.
"I know – a garage is not what comes to mind when you think clean," laughs Casey Ashdown, who started what is today Zerorez of Phoenix in his garage in 2004. "It was a very different kind of place to launch an office, but we wanted to be a very different kind of cleaning company."
Ashdown first got into the idea of launching Zerorez in the Valley from his brother, who worked for a Zerorez sister franchise in another state.
"Unlike traditional carpet cleaning companies that use a method of hot water extraction using soaps, detergents and harsh chemicals that get left behind in the carpet fibers, we saw firsthand how Zerorez used this 'Empowered Water,' a water-based, non-toxic cleaning agent that leaves no soil-attracting residue behind," said Ashdown. "And we don't just focus on carpets. In fact, we offer tile and grout cleaning; upholstery cleaning; area rug cleaning; pet odor treatment; hard surfaces cleaning and even mattress cleaning in addition to carpets."
Ashdown couldn't believe no one had launched the concept in Arizona – and jumped at the chance, bringing in his brother-in-law Nathan Perrins as a partner and to assist with marketing.
"Thankfully, we weren't the only ones who liked the idea of this Empowered Water, and the business grew by leaps and bounds. So much so, we expanded into Deer Valley two years ago," said Ashdown. "Moving here allowed us to alleviate some of the commuting hardship that our employees living in the North Valley experienced as they traveled back and forth. Now, nearly 20 members of our team are working out of this location and doing a fantastic job at servicing the area."
Zerorez growth under Ashdown and Perrins over the past decade-plus has not been just swift, but responsible.
"We didn't want to just add bodies to our business – and we didn't just want to provide service to communities then be done with them until next time," said Perrins. "So, we made a conscious effort to find ways to give back, not to mention ways for our rapidly expanding team to work together for the greater good."
One of the most effective programs they put into place – The Rezoteer Volunteer Program.
"The Rezoteer Volunteer Program provides our Zerorez staff and their family members a way to get involved with volunteer projects in their local communities and to share in the benefits of giving back alongside their co-workers," said Perrins.
Ashdown and Perrins also developed Zero 2 Hero Program, which helps to raise critical funds for organizations serving children throughout the Valley.
"March was a big one for Zero 2 Hero. Throughout the month, we collected a portion of all of our proceeds to benefit the Phoenix Children's Hospital, raising $5,800, which we donated in April," said Ashdown. "Altogether, we've been able to collect a total of $26,000 for PHC over the past five years, with all the funds being used to directly impact research and care for the children at the hospital."
For Ashdown and the Zerorez team, many of whom are fathers and mothers themselves, the cause is especially personal.
"One of my daughters was born at just 24 weeks, weighing only one pound and ten ounces. I have seen firsthand the tireless work that doctors, nurses and the rest of the staff at Arizona's amazing hospitals do each and every day," said Ashdown. "The fact that we can – even in just this small way – help these heroes and their tiny patients is among the proudest accomplishments of being small business owners in this community."
A 2015 Better Business Bureau Ethics Award Winner for work like this, today the business has more than 70 employees and 31 vans Valleywide.
"And we're just getting started," said Ashdown.
www.zerorezphoenix.com.
By voloadmin|2019-07-06T08:22:06+00:00May 1st, 2016|All Category, Business DVT, News DVT|Comments Off on Zerorez of Phoenix Expands to Deer Valley; Focused on Cleaning Up While Giving Back
About the Author: voloadmin
Hiring Tips and Resources for a New Job in 2021
12 Ways to Support Local Small Businesses In The New Year
Why You Need To Re-Vamp Your Website in 2021
The Benefits of Crafty Virtual Team Builders
Hi, my name is… Tamra Wyman of Wyman Plumbing & Mechanical LLC
1825 E Northern Ave.,
STE 205, Phoenix AZ 85020
www.egpublishing.com
Aging workforce, technical skills shortage and the importance of CTE
By Greg Donovan, Superintendent at Western Maricopa […]
The COVID-19 pandemic has had an impact on almost […]
The New Year can bring on new problems for small […]
Copyright © year, EG Publishing - All Rights Reserved. | Web Designed & Developed by: Powerhouse Group

redpajama_set_name: RedPajamaCommonCrawl


Glenn Greenwald on Wednesday said that the head of the U.S. National Security Agency, General Keith Alexander, did not offer "any evidence" when he told Congress on Tuesday that the NSA did not collect data on millions of citizens in Europe.
"Notice what he didn't offer, which is any evidence for the truth of what he's is saying," Greenwald said in an interview with CNN's Christiane Amanpour.
Greenwald is the activist and journalist who broke the story of NSA snooping and has a trove a leaked documents from former intelligence staffer Edward Snowden.
On Tuesday, General Alexander went before Congress and batted down media reports that the NSA had collected data on tens of millions of phone calls in a single month in France and Spain.
As to whether he himself could have made a mistake, Greenwald did not reject the idea, but stood by his reporting.
UPDATE: A previous version of this article mistakenly referred to the NSA as the National Security Administration. It is the National Security Agency.
Do the Chinese ever acknowledge what they are upto ? This is a complex world and if the technology is there, always safer – and in the public interest – to scoop up a little more than letting a lethal signal slip by.
The Chinese don't have to admit to anything – they don't get caught. Otherwise, we'd be seeing articles like this every week. Besides, the Chinese have little reason to spy on anyone for terrorism. How many suicide/automobile bombings in China in the last 10 years? Count 'em on one hand. And ZERO from al-Qaeda. As soon as the Chinese government even gets a *hint* of an attack, everyone involved (and a few who might not be) goes to jail. This government (as I live and work there, but I'm a US citizen) brooks no dissent and certainly fears no outside terrorism.
I didn't know the prime ministers of Germany and Spain were the enemies of the USA.
Glenn Greenwald for technology innovation fake apple, microsofl, android phone and a chip trap and hidden evil trick NSA South Korea, China and used stolen money millionaires company sell world religion, race, language and so on ... lack francisco I respected Pope Benedict XVI and Tiwtter cell, facebook and news goes.
I'm sympathetic to the point but I'm not sure how they would they provide evidence that they didn't spy on someone. Can you provide evidence that you never listened to Justin Beiber music on purpose?
So he's saying that the secret agency cannot be governed. Or that lying is the most incredible thing that has ever been discovered. I know, you're saying the NSA's leadership cannot govern the agency 'cause they don't know what it's doing. But what about a secret court? A court with judges appointed by one person. And that one person is not accountable to anyone but God (Supreme Court Chief Justice Roberts, who's appointed all the FISA judges). Roberts does not answer to the president or the House. Secret court, something wrong with that concept overseeing anything.
Who's that Greenwald guy? Has he been appointed by god?
By the way, how exactly does one present "evidence" of something one hasn't done? Greenwald accuses, and the burden of proof **is on him**, not the gov't! How are they supposed to prove something they claim they don't have? Greenwald must be losing his 15 minutes of fame too fast and just wants to keep his name up.
I wish NSA or other body whose most pressing mission is to stop the Jihaddist madness was devouring all kinds of chatters and sifting through that and had unearthed the plot to kill the 2 daring French journalists ( they r real journalists ) and related that to the French forces who were near by in Mali.The NSA most probably is staffed by real Pros who wouldn't dwell on someones petty conversation, jibberish or even conversation about serious subject if it has no bearing on their assignment, which is mainly eliminating sec threats that can derail serious business.To use an analogy : I am adept at making a delicious lentil soup.2 make the soup one buys a not too long ago harvested lentil, take it 2 the kitchen, carefully isolate the soil and sand particles whose color resembles the lentil or other residues discard those and then finally make an actual soup.At the begining it is, almost all the time unavoidable to first grab a fist full of the crude lentil and spread it.For 5 years right after 9/11 I used 2 live in the US and there was uneasy feeling of being scrutinized more than the pre-9/11 era.But that was a sign of the changed time.But because almost eveyrone was being scrutinized more than what was common it was hardly the case that individuals with no intention of deliberately hurting innocents were unnecessarily tripped based on the fleeting knowledge about them.So, what good reason can there b 4 making so much clamor about NSA, European and other responsible intelligence agencies ?.Either we want 2 live in a reliably safe World or not.That, in an effort to do things meticulously, some excesses occur may not b fully avoidable from the Intel business.TW, a Mthematician who made 7 years since leaving the US, from A.A..
Someone needs to advise folks like Snowden and Greenwald to grow up. Sometimes i wish People like them had tasted the brutality of al-qaeda; taliban; or any of the planned attacks that the NSA stopped/foiled. In the USA there are many examples whereby an individual changed the way government operates by talking, using the right channels, not the way Snowden did. You can't run to places like China and spill the beans there, a place where the government can eavesdrop on anyone anyway and Folks are not allowed to complain loudly. Snowden and Greenwald should know that nations spy on each other (even friends)and even their own citizens if they feel they are a security risk. In some banana republics operatives use the apparatus for personal ends, you guys are fortunate. Snowden should be enjoying the media coverage and sensationalism caused by his emotional immaturity not whining about the treatment he is getting!
why do they want to listn to phone calls anyways.


One possible motive for the shooting of Suge Knight at Chris Brown's album release party was to discourage him from releasing a tell-all book on his music industry reign.
Music insiders are buzzing that Knight is shopping a story on his career, from founding Death Row Records in the early '90s to his hard-handed business dealings, including the legendary tale of holding Vanilla Ice over a hotel balcony to obtain rights to his radio hit "Ice Ice Baby." Knight was also driving the BMW in which Tupac Shakur was fatally shot by an unknown assailant.
Knight had a deal with Penguin's Riverhead Books to write his autobiography in 2002, but it was never released. The music mogul has since fallen into legal and financial trouble, having filed for bankruptcy in 2006 after losing a $107 million lawsuit to a woman who claimed she helped found Death Row with Knight.
We're told that Knight — who's refused to talk to police about last weekend's shooting — was also recently shopping a movie and had filmed a pilot for a reality show a few years ago, though it's never aired. "Suge doing a tell-all book would be a huge best seller, and probably one of the few things he could do," a source told us.
Knight and two other men were hit with bullets at Brown's album release party at 1Oak in West Hollywood early Sunday morning during the VMAs weekend. Knight was released from the hospital Wednesday morning.
The statute of limitations might be up on some of Suge's previous shady dealings with nefarious characters, but we're sure that those folks would rather him keep his damn mouth shut.


Christoph Eschenbach conducts the Boston Symphony Orchestra with Midori as soloist at Tanglewood Music Festival on Saturday.
LENOX — In the world of classical music, centenary celebrations can cut both ways. They can provide a welcome opportunity to reconsider reputations, rediscover bodies of work, and reappraise former certainties. Yet at the same time, they also tend to accentuate less salutary myths of golden ages past, the notion that the present is but a pale imitation of musical life back then, when gods and heroes bestrode our stages and when composers wrote the only music that, so the thinking goes, still deserves to be played.
Both sides of the centennial equation have held true in the case of Leonard Bernstein, whose 100th birthday has been toasted this year across the classical music world and most of all here at Tanglewood. The historic festival organized its entire summer schedule under the banner of "Celebrating Lenny." And on Saturday, the day that Bernstein would have turned 100, it pulled out all the stops with a high-wattage gala concert in grand Lenny style.
As a location for this particular centenary's culminating event, Tanglewood was a natural choice. This was where it all began for Bernstein, where he led his first orchestra in 1940. It was the place where his deeply influential relationship with the conductor Serge Koussevitzky took root. In later decades, it was where he returned often, quite literally wrapping himself in Koussevitzky's cloaks. It was also where his career ended, after his final concert here in 1990.
Yet all of that said, it's also worth remembering one episode less frequently recounted among the plentiful Bernstein anecdotes in local circulation: The BSO of midcentury chose to disregard Koussevitzky's wish that Bernstein succeed him as the BSO's own music director. The board instead went with the debonair European maestro Charles Munch. The snub could not hold back a figure like Bernstein for long. Still, it's hard not to wonder how things would have turned out differently if the BSO's trustees had taken a risk on the young Lenny back then.
One early highlight of the night was the violinist Midori's deeply felt account of the first movement from Bernstein's "Serenade," the work with which she made her BSO debut in 1986 under Bernstein's baton (a performance during which she famously broke a string not only on her own violin but also that of the concertmaster). Nadine Sierra was the soprano soloist in a movement from the "Kaddish" Symphony led by Keith Lockhart, and Tilson-Thomas conducted a stylishly fluid account of selections from "West Side Story." After intermission came brief selections by Mahler and Copland before Andris Nelsons returned to the stage to lead the massed instrumental forces, together with the Tanglewood Festival Chorus and vocal soloists, in a rousing account of the finale from Mahler's Second Symphony.
Punctuating the music were two brief films, rich with archival footage and reflections on Bernstein's career from the likes of Gustavo Dudamel, Marin Alsop, Andrew Lloyd Webber, and Stephen Sondheim. But if Saturday night's tribute had a second starring character, it was the Tanglewood festival itself. In so many stories, Bernstein's musical coming-of-age seems to personify the idealistic era of Tanglewood's own youth. As Williams stated in one film: "For the time that he was there, he was Tanglewood. And Tanglewood was Lenny." As another speaker recalled, there were even meteorological affinities between the festival and its native star. Hence the term "Bernstein weather," coined to describe the gloriously cloudless skies that his concerts seemed to attract with uncanny frequency.
Bernstein's political engagement, his insistence on the enduring linkages between art and society, was one aspect of the composer's legacy raised only obliquely on Saturday. Yet this aspect was amplified in Sunday afternoon's season-closing concert. The bulk of the program was devoted to the traditional account of Beethoven's Ninth Symphony — given a vigorous performance under Eschenbach's direction, with particularly affecting contributions by the Tanglewood Festival Chorus. This was the final outing for a large number of outgoing TFC singers — a fact that did not go unnoticed by the delighted Shed audiences or by members of the BSO, many of whom, in a striking gesture, turned their backs to the crowd and applauded the singers directly.
Bernstein sets these lines with a glowing tenderness, and mezzo-soprano Sasha Cooke sang them on Sunday in a manner at once radiant and knowing. The song's resonance, and its devastating critique, needed no elaboration. The music seemed to wash over the Shed and out onto the lawn, where thousands of listeners were seated on blankets and chairs, enjoying — one more time — the Bernstein weather.


Book by Jose Silva & Robert B. Stone Ph.D.
Perfect health is your body's natural state. Get this step-by-step guide to gaining invincible health with Silva Mental training.
This is one of the best books written about the Silva Method and required reading if you want to achieve true health and wellness.
Getting Well Again by O. Carl Simonton, M.D.