普通文本  |  365行  |  14.41 KB

// Copyright 2014 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 "athena/wm/public/window_manager.h"

#include "athena/screen/public/screen_manager.h"
#include "athena/test/athena_test_base.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/split_view_controller.h"
#include "athena/wm/test/window_manager_impl_test_api.h"
#include "athena/wm/window_manager_impl.h"
#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/wm/core/window_util.h"

namespace athena {

class WindowManagerTest : public test::AthenaTestBase {
 public:
  WindowManagerTest() {}
  virtual ~WindowManagerTest() {}

  scoped_ptr<aura::Window> CreateAndActivateWindow(
      aura::WindowDelegate* delegate) {
    scoped_ptr<aura::Window> window(CreateTestWindow(delegate, gfx::Rect()));
    window->Show();
    wm::ActivateWindow(window.get());
    return window.Pass();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(WindowManagerTest);
};

TEST_F(WindowManagerTest, OverviewModeBasics) {
  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));

  test::WindowManagerImplTestApi wm_api;
  wm::ActivateWindow(second.get());

  ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
  EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());
  EXPECT_EQ(gfx::Screen::GetNativeScreen()
                ->GetPrimaryDisplay()
                .work_area()
                .size()
                .ToString(),
            first->bounds().size().ToString());
  EXPECT_FALSE(WindowManager::Get()->IsOverviewModeActive());

  // Tests that going into overview mode does not change the window bounds.
  WindowManager::Get()->ToggleOverview();
  ASSERT_TRUE(WindowManager::Get()->IsOverviewModeActive());
  EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());
  EXPECT_EQ(gfx::Screen::GetNativeScreen()
                ->GetPrimaryDisplay()
                .work_area()
                .size()
                .ToString(),
            first->bounds().size().ToString());
  EXPECT_TRUE(first->IsVisible());
  EXPECT_TRUE(second->IsVisible());

  // Terminate overview mode. |first| should be hidden, since it's not visible
  // to the user anymore.
  WindowManager::Get()->ToggleOverview();
  ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
  EXPECT_FALSE(first->IsVisible());
  EXPECT_TRUE(second->IsVisible());
}

TEST_F(WindowManagerTest, OverviewToSplitViewMode) {
  test::WindowManagerImplTestApi wm_api;

  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));
  wm::ActivateWindow(w3.get());

  WindowManager::Get()->ToggleOverview();
  EXPECT_TRUE(w1->IsVisible());
  EXPECT_TRUE(w2->IsVisible());
  EXPECT_TRUE(w3->IsVisible());

  // Go into split-view mode.
  WindowOverviewModeDelegate* overview_delegate = wm_api.wm();
  overview_delegate->OnSelectSplitViewWindow(w3.get(), NULL, w3.get());
  EXPECT_TRUE(w3->IsVisible());
  EXPECT_TRUE(w2->IsVisible());
  EXPECT_FALSE(w1->IsVisible());
}

TEST_F(WindowManagerTest, NewWindowFromOverview) {
  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));

  WindowManager::Get()->ToggleOverview();
  EXPECT_TRUE(w1->IsVisible());
  EXPECT_TRUE(w2->IsVisible());

  // Test that opening a new window exits overview mode. The new window could
  // have been opened by JavaScript or by the home card.
  scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));

  ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
  EXPECT_TRUE(w3->IsVisible());
  EXPECT_TRUE(wm::IsActiveWindow(w3.get()));
  EXPECT_FALSE(w1->IsVisible());
  EXPECT_FALSE(w2->IsVisible());
}

TEST_F(WindowManagerTest, BezelGestureToSplitViewMode) {
  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));

  test::WindowManagerImplTestApi wm_api;

  // Test that going into split-view mode with two-finger gesture selects the
  // correct windows on left and right splits.
  ui::test::EventGenerator generator(root_window());
  const gfx::Point start_points[2] = {
      gfx::Point(2, 10), gfx::Point(4, 20),
  };
  const int kEventTimeSepration = 16;
  int x_middle = root_window()->bounds().width() / 2;
  generator.GestureMultiFingerScroll(
      2, start_points, kEventTimeSepration, 1, x_middle, 0);
  ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
  EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
  EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window());
  EXPECT_EQ(second->bounds().size().ToString(),
            third->bounds().size().ToString());
}

TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) {
  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
  first->Hide();
  second->Hide();

  test::WindowManagerImplTestApi wm_api;

  EXPECT_EQ(third.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());

  // Do a two-finger swipe from the left bezel.
  ui::test::EventGenerator generator(root_window());
  const gfx::Point left_bezel_points[2] = {
      gfx::Point(2, 10), gfx::Point(4, 20),
  };
  const int kEventTimeSeparation = 16;
  int width = root_window()->bounds().width();
  generator.GestureMultiFingerScroll(
      2, left_bezel_points, kEventTimeSeparation, 1, width, 0);
  EXPECT_TRUE(wm::IsActiveWindow(second.get()));
  EXPECT_EQ(second.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());

  // Do a two-finger swipe from the right bezel.
  const gfx::Point right_bezel_points[2] = {
      gfx::Point(width - 5, 10),
      gfx::Point(width - 10, 20)
  };
  generator.GestureMultiFingerScroll(
      2, right_bezel_points, kEventTimeSeparation, 1, -width, 0);
  EXPECT_TRUE(wm::IsActiveWindow(third.get()));
  EXPECT_EQ(third.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());
}

TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindows) {
  aura::test::TestWindowDelegate delegate;
  delegate.set_window_component(HTCAPTION);
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));

  test::WindowManagerImplTestApi wm_api;

  EXPECT_EQ(third.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());

  // Do a title-swipe from the top to switch to the previous window.
  ui::test::EventGenerator generator(root_window());
  generator.GestureScrollSequence(gfx::Point(20, 10),
                                  gfx::Point(20, 400),
                                  base::TimeDelta::FromMilliseconds(20),
                                  5);
  EXPECT_TRUE(wm::IsActiveWindow(second.get()));
  EXPECT_EQ(second.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());
  EXPECT_TRUE(second->IsVisible());
  EXPECT_FALSE(third->IsVisible());

  // Performing the same gesture again will switch back to |third|.
  generator.GestureScrollSequence(gfx::Point(20, 10),
                                  gfx::Point(20, 400),
                                  base::TimeDelta::FromMilliseconds(20),
                                  5);
  EXPECT_TRUE(wm::IsActiveWindow(third.get()));
  EXPECT_EQ(third.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());
  EXPECT_FALSE(second->IsVisible());
  EXPECT_TRUE(third->IsVisible());

  // Perform a swipe that doesn't go enough to perform the window switch.
  generator.GestureScrollSequence(gfx::Point(20, 10),
                                  gfx::Point(20, 90),
                                  base::TimeDelta::FromMilliseconds(20),
                                  5);
  EXPECT_TRUE(wm::IsActiveWindow(third.get()));
  EXPECT_EQ(third.get(),
            wm_api.GetWindowListProvider()->GetWindowList().back());
  EXPECT_FALSE(second->IsVisible());
  EXPECT_TRUE(third->IsVisible());
}

TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindowsInSplitViewMode) {
  aura::test::TestWindowDelegate delegate;
  delegate.set_window_component(HTCAPTION);
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> fourth(CreateAndActivateWindow(&delegate));

  test::WindowManagerImplTestApi wm_api;

  // Test that going into split-view mode with two-finger gesture selects the
  // correct windows on left and right splits.
  ui::test::EventGenerator generator(root_window());
  const gfx::Point start_points[2] = {
      gfx::Point(2, 10), gfx::Point(4, 20),
  };
  const int kEventTimeSepration = 16;
  int x_middle = root_window()->bounds().width() / 2;
  generator.GestureMultiFingerScroll(
      2, start_points, kEventTimeSepration, 1, x_middle, 0);
  ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
  EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->left_window());
  EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window());

  // Swipe the title of the left window. It should switch to |second|.
  generator.GestureScrollSequence(gfx::Point(20, 10),
                                  gfx::Point(20, 400),
                                  base::TimeDelta::FromMilliseconds(20),
                                  5);
  EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
  EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window());
  aura::Window::Windows windows =
      wm_api.GetWindowListProvider()->GetWindowList();
  ASSERT_EQ(4u, windows.size());
  EXPECT_EQ(second.get(), windows[3]);
  EXPECT_EQ(fourth.get(), windows[2]);

  // Swipe the title of the right window now. It should switch to |third|.
  generator.GestureScrollSequence(gfx::Point(x_middle + 20, 10),
                                  gfx::Point(x_middle + 20, 400),
                                  base::TimeDelta::FromMilliseconds(20),
                                  5);
  EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
  EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window());
  windows = wm_api.GetWindowListProvider()->GetWindowList();
  ASSERT_EQ(4u, windows.size());
  EXPECT_EQ(third.get(), windows[3]);
  EXPECT_EQ(second.get(), windows[2]);
}

TEST_F(WindowManagerTest, NewWindowBounds) {
  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));

  test::WindowManagerImplTestApi wm_api;
  // The window should have the same size as the container.
  const gfx::Size work_area =
      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size();
  EXPECT_EQ(work_area.ToString(),
            first->bounds().size().ToString());
  EXPECT_TRUE(first->bounds().origin().IsOrigin());

  // A second window should have the same bounds as the first one.
  scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
  EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());

  // Get into split view.
  wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL);
  const gfx::Rect left_bounds =
      wm_api.GetSplitViewController()->left_window()->bounds();
  EXPECT_NE(work_area.ToString(),
            left_bounds.size().ToString());

  // A new window should replace the left window when in split view.
  scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
  EXPECT_EQ(wm_api.GetSplitViewController()->left_window(), third.get());
  EXPECT_EQ(left_bounds.ToString(), third->bounds().ToString());
}

TEST_F(WindowManagerTest, SplitModeActivationByShortcut) {
  test::WindowManagerImplTestApi wm_api;

  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));

  // Splitview mode needs at least two windows.
  wm_api.wm()->ToggleSplitView();
  EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());

  scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
  w2->Show();

  wm_api.wm()->ToggleSplitView();
  EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
  int width =
      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().width();

  EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
  EXPECT_GE(width / 2, w1->bounds().width());

  // Toggle back to normal mode.
  wm_api.wm()->ToggleSplitView();
  EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());

  EXPECT_EQ(width, w1->bounds().width());
  EXPECT_EQ(width, w2->bounds().width());
}

TEST_F(WindowManagerTest, OverviewModeFromSplitMode) {
  test::WindowManagerImplTestApi wm_api;

  aura::test::TestWindowDelegate delegate;
  scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
  scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));

  // Get into split-view mode, and then turn on overview mode.
  wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL);
  WindowManager::Get()->ToggleOverview();
  EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
  EXPECT_EQ(w3.get(), wm_api.GetSplitViewController()->left_window());
  EXPECT_EQ(w2.get(), wm_api.GetSplitViewController()->right_window());

  WindowOverviewModeDelegate* overview_delegate = wm_api.wm();
  overview_delegate->OnSelectWindow(w1.get());
  EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
  EXPECT_TRUE(w1->IsVisible());
  // Make sure the windows that were in split-view mode are hidden.
  EXPECT_FALSE(w2->IsVisible());
  EXPECT_FALSE(w3->IsVisible());
}

}  // namespace athena