root/chrome/browser/ui/ash/window_positioner_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetNativeWindow
  2. window
  3. popup
  4. window_browser
  5. popup_browser
  6. window_positioner
  7. window_positioner_
  8. SetUp
  9. TearDown
  10. AlignToGridRoundDown
  11. TEST_F
  12. TEST_F
  13. TEST_F

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/window_positioner.h"

#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_shell_delegate.h"
#include "ash/wm/window_resizer.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/render_view_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/env.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/gfx/screen.h"

namespace ash {
namespace test {

namespace {

// A browser window proxy which is able to associate an aura native window with
// it.
class TestBrowserWindowAura : public TestBrowserWindow {
 public:
  explicit TestBrowserWindowAura(aura::Window* native_window);
  virtual ~TestBrowserWindowAura();

  virtual gfx::NativeWindow GetNativeWindow() OVERRIDE {
    return native_window_;
  }

 private:
  gfx::NativeWindow native_window_;

  DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura);
};

TestBrowserWindowAura::TestBrowserWindowAura(aura::Window *native_window)
    : native_window_(native_window) {
}

TestBrowserWindowAura::~TestBrowserWindowAura() {}

}  // namespace

// A test class for preparing window positioner tests - it creates a testing
// base by adding a window and a popup which can be independently
// positioned to see where the positioner will place the window.
class WindowPositionerTest : public AshTestBase {
 public:
  WindowPositionerTest();

  virtual void SetUp() OVERRIDE;
  virtual void TearDown() OVERRIDE;

 protected:
  aura::Window* window() { return window_.get(); }
  aura::Window* popup() { return popup_.get(); }

  Browser* window_browser() { return window_owning_browser_.get(); }
  Browser* popup_browser() { return popup_owning_browser_.get(); }

  WindowPositioner* window_positioner() { return window_positioner_; }

  // The positioner & desktop's used grid alignment size.
  const int grid_size_;

 private:
  WindowPositioner* window_positioner_;

  // These two need to be deleted after everything else is gone.
  TestingProfile profile_;

  // These get created for each session.
  scoped_ptr<aura::Window> window_;
  scoped_ptr<aura::Window> popup_;

  scoped_ptr<BrowserWindow> browser_window_;
  scoped_ptr<BrowserWindow> browser_popup_;

  scoped_ptr<Browser> window_owning_browser_;
  scoped_ptr<Browser> popup_owning_browser_;

  DISALLOW_COPY_AND_ASSIGN(WindowPositionerTest);
};

WindowPositionerTest::WindowPositionerTest()
    : grid_size_(WindowPositioner::kMinimumWindowOffset),
      window_positioner_(NULL) {
}

void WindowPositionerTest::SetUp() {
  AshTestBase::SetUp();
  // Create some default dummy windows.
  window_.reset(CreateTestWindowInShellWithId(0));
  window_->SetBounds(gfx::Rect(16, 32, 640, 320));
  popup_.reset(CreateTestWindowInShellWithId(1));
  popup_->SetBounds(gfx::Rect(16, 32, 128, 256));

  // Create a browser for the window.
  browser_window_.reset(new TestBrowserWindowAura(window_.get()));
  Browser::CreateParams window_params(&profile_,
                                      chrome::HOST_DESKTOP_TYPE_ASH);
  window_params.window = browser_window_.get();
  window_owning_browser_.reset(new Browser(window_params));

  // Creating a browser for the popup.
  browser_popup_.reset(new TestBrowserWindowAura(popup_.get()));
  Browser::CreateParams popup_params(Browser::TYPE_POPUP, &profile_,
                                     chrome::HOST_DESKTOP_TYPE_ASH);
  popup_params.window = browser_popup_.get();
  popup_owning_browser_.reset(new Browser(popup_params));

  // We hide all windows upon start - each user is required to set it up
  // as he needs it.
  window()->Hide();
  popup()->Hide();
  window_positioner_ = new WindowPositioner();
}

void WindowPositionerTest::TearDown() {
  // Since the AuraTestBase is needed to create our assets, we have to
  // also delete them before we tear it down.
  window_owning_browser_.reset(NULL);
  popup_owning_browser_.reset(NULL);

  browser_window_.reset(NULL);
  browser_popup_.reset(NULL);

  window_.reset(NULL);
  popup_.reset(NULL);

  AshTestBase::TearDown();
  delete window_positioner_;
  window_positioner_ = NULL;
}

int AlignToGridRoundDown(int location, int grid_size) {
  if (grid_size <= 1 || location % grid_size == 0)
    return location;
  return location / grid_size * grid_size;
}

TEST_F(WindowPositionerTest, cascading) {
  const gfx::Rect work_area =
      Shell::GetScreen()->GetPrimaryDisplay().work_area();

  // First see that the window will cascade down when there is no space.
  window()->SetBounds(work_area);
  window()->Show();

  gfx::Rect popup_position(0, 0, 200, 200);
  // Check that it gets cascaded.
  gfx::Rect cascade_1 = window_positioner()->GetPopupPosition(popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x() + grid_size_, work_area.y() + grid_size_,
                      popup_position.width(), popup_position.height()),
                      cascade_1);

  gfx::Rect cascade_2 = window_positioner()->GetPopupPosition(popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x() + 2 * grid_size_,
                      work_area.y() + 2 * grid_size_,
                      popup_position.width(), popup_position.height()),
                      cascade_2);

  // Check that if there is even only a pixel missing it will cascade.
  window()->SetBounds(gfx::Rect(work_area.x() + popup_position.width() - 1,
                                work_area.y() + popup_position.height() - 1,
                                work_area.width() -
                                    2 * (popup_position.width() - 1),
                                work_area.height() -
                                    2 * (popup_position.height() - 1)));

  gfx::Rect cascade_3 = window_positioner()->GetPopupPosition(popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x() + 3 * grid_size_,
                      work_area.y() + 3 * grid_size_,
                      popup_position.width(), popup_position.height()),
                      cascade_3);

  // Check that we overflow into the next line when we do not fit anymore in Y.
  gfx::Rect popup_position_4(0, 0, 200,
                             work_area.height() -
                                 (cascade_3.y() - work_area.y()));
  gfx::Rect cascade_4 =
      window_positioner()->GetPopupPosition(popup_position_4);
  EXPECT_EQ(gfx::Rect(work_area.x() + 2 * grid_size_,
                      work_area.y() + grid_size_,
                      popup_position_4.width(), popup_position_4.height()),
                      cascade_4);

  // Check that we overflow back to the first possible location if we overflow
  // to the end.
  gfx::Rect popup_position_5(0, 0,
                            work_area.width() + 1 -
                                (cascade_4.x() - work_area.x()),
                            work_area.height() -
                                (2 * grid_size_ - work_area.y()));
  gfx::Rect cascade_5 =
      window_positioner()->GetPopupPosition(popup_position_5);
  EXPECT_EQ(gfx::Rect(work_area.x() + grid_size_,
                      work_area.y() + grid_size_,
                      popup_position_5.width(), popup_position_5.height()),
                      cascade_5);
}

TEST_F(WindowPositionerTest, filling) {
  const gfx::Rect work_area =
      Shell::GetScreen()->GetPrimaryDisplay().work_area();
  gfx::Rect popup_position(0, 0, 256, 128);
  // Leave space on the left and the right and see if we fill top to bottom.
  window()->SetBounds(gfx::Rect(work_area.x() + popup_position.width(),
                                work_area.y(),
                                work_area.width() - 2 * popup_position.width(),
                                work_area.height()));
  window()->Show();
  // Check that we are positioned in the top left corner.
  gfx::Rect top_left = window_positioner()->GetPopupPosition(popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x(), work_area.y(),
                      popup_position.width(), popup_position.height()),
                      top_left);

  // Now block the found location.
  popup()->SetBounds(top_left);
  popup()->Show();
  gfx::Rect mid_left = window_positioner()->GetPopupPosition(popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x(),
                      AlignToGridRoundDown(
                          work_area.y() + top_left.height(), grid_size_),
                          popup_position.width(), popup_position.height()),
                      mid_left);

  // Block now everything so that we can only put the popup on the bottom
  // of the left side.
  // Note: We need to keep one "grid spacing free" if the window does not
  // fit into the grid (which is true for 200 height).`
  popup()->SetBounds(gfx::Rect(work_area.x(), work_area.y(),
                               popup_position.width(),
                               work_area.height() - popup_position.height() -
                                   grid_size_ + 1));
  gfx::Rect bottom_left = window_positioner()->GetPopupPosition(
                              popup_position);
  EXPECT_EQ(gfx::Rect(work_area.x(),
                      work_area.bottom() - popup_position.height(),
                      popup_position.width(), popup_position.height()),
                      bottom_left);

  // Block now enough to force the right side.
  popup()->SetBounds(gfx::Rect(work_area.x(), work_area.y(),
                               popup_position.width(),
                               work_area.height() - popup_position.height() +
                               1));
  gfx::Rect top_right = window_positioner()->GetPopupPosition(
                            popup_position);
  EXPECT_EQ(gfx::Rect(AlignToGridRoundDown(work_area.right() -
                                           popup_position.width(), grid_size_),
                      work_area.y(),
                      popup_position.width(), popup_position.height()),
                      top_right);
}

TEST_F(WindowPositionerTest, biggerThenBorder) {
  const gfx::Rect work_area =
      Shell::GetScreen()->GetPrimaryDisplay().work_area();

  gfx::Rect pop_position(0, 0, work_area.width(), work_area.height());

  // Check that the popup is placed full screen.
  gfx::Rect full = window_positioner()->GetPopupPosition(pop_position);
  EXPECT_EQ(gfx::Rect(work_area.x(), work_area.y(),
                      pop_position.width(), pop_position.height()),
                      full);
}

}  // namespace test
}  // namespace ash

/* [<][>][^][v][top][bottom][index][help] */