Home | History | Annotate | Download | only in wm
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "athena/wm/window_list_provider_impl.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "athena/test/athena_test_base.h"
     10 #include "athena/wm/public/window_list_provider_observer.h"
     11 #include "ui/aura/test/test_window_delegate.h"
     12 #include "ui/aura/window.h"
     13 
     14 namespace athena {
     15 
     16 namespace {
     17 
     18 bool AreWindowListsEqual(const aura::Window::Windows& one,
     19                          const aura::Window::Windows& two) {
     20   return one.size() == two.size() &&
     21          std::equal(one.begin(), one.end(), two.begin());
     22 }
     23 
     24 scoped_ptr<aura::Window> CreateWindow(aura::WindowDelegate* delegate,
     25                                       ui::wm::WindowType window_type) {
     26   scoped_ptr<aura::Window> window(new aura::Window(delegate));
     27   window->SetType(window_type);
     28   window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
     29   return window.Pass();
     30 }
     31 
     32 // Return a string which defines the order of windows in |now| using the indices
     33 // of |original|. The string will then have the lowest/oldest window on the left
     34 // and the highest / newest on the right.
     35 std::string GetWindowOrder(const aura::Window::Windows& original,
     36                            const aura::Window::Windows& now) {
     37   if (original.size() != now.size())
     38     return "size has changed.";
     39   std::string output;
     40   for (aura::Window::Windows::const_iterator it = now.begin();
     41        it != now.end(); ++it) {
     42     for (size_t i = 0; i < original.size(); i++) {
     43       if ((*it) == original[i]) {
     44         output += (output.size() ? " " : std::string()) +
     45                   std::to_string(i + 1);
     46         break;
     47       }
     48     }
     49   }
     50   return output;
     51 }
     52 
     53 class WindowListObserver : public WindowListProviderObserver {
     54  public:
     55   explicit WindowListObserver(WindowListProvider* provider)
     56       : calls_(0), window_removal_calls_(0), provider_(provider) {
     57     provider_->AddObserver(this);
     58   }
     59   virtual ~WindowListObserver() {
     60     provider_->RemoveObserver(this);
     61   }
     62 
     63   int calls() const { return calls_; }
     64   int window_removal_calls() const { return window_removal_calls_; }
     65 
     66   // WindowListProviderObserver:
     67   virtual void OnWindowStackingChanged() OVERRIDE {
     68     calls_++;
     69   }
     70 
     71   virtual void OnWindowRemoved(aura::Window* removed_window,
     72                                int index) OVERRIDE {
     73     window_removal_calls_++;
     74   }
     75 
     76  private:
     77   // The number of calls to the observer.
     78   int calls_;
     79   int window_removal_calls_;
     80 
     81   // The associated WindowListProvider which is observed.
     82   WindowListProvider* provider_;
     83 
     84   DISALLOW_COPY_AND_ASSIGN(WindowListObserver);
     85 };
     86 
     87 
     88 }  // namespace
     89 
     90 typedef test::AthenaTestBase WindowListProviderImplTest;
     91 
     92 // Tests that the order of windows match the stacking order of the windows in
     93 // the container, even after the order is changed through the aura Window API.
     94 TEST_F(WindowListProviderImplTest, StackingOrder) {
     95   aura::test::TestWindowDelegate delegate;
     96   scoped_ptr<aura::Window> container(new aura::Window(&delegate));
     97   scoped_ptr<aura::Window> first =
     98       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
     99   scoped_ptr<aura::Window> second =
    100       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    101   scoped_ptr<aura::Window> third =
    102       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    103   container->AddChild(first.get());
    104   container->AddChild(second.get());
    105   container->AddChild(third.get());
    106 
    107   scoped_ptr<WindowListProvider> list_provider(
    108       new WindowListProviderImpl(container.get()));
    109   EXPECT_TRUE(AreWindowListsEqual(container->children(),
    110                                   list_provider->GetWindowList()));
    111 
    112   container->StackChildAtTop(first.get());
    113   EXPECT_TRUE(AreWindowListsEqual(container->children(),
    114                                   list_provider->GetWindowList()));
    115   EXPECT_EQ(first.get(), container->children().back());
    116 }
    117 
    118 // Tests that only normal windows of the associated container will be listed.
    119 TEST_F(WindowListProviderImplTest, ListContainsOnlyNormalWindows) {
    120   aura::test::TestWindowDelegate delegate;
    121   scoped_ptr<aura::Window> container(new aura::Window(&delegate));
    122   scoped_ptr<aura::Window> first =
    123       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    124   scoped_ptr<aura::Window> second =
    125       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP);
    126   scoped_ptr<aura::Window> third =
    127       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    128   scoped_ptr<aura::Window> fourth =
    129       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU);
    130   container->AddChild(first.get());
    131   container->AddChild(second.get());
    132   container->AddChild(third.get());
    133   container->AddChild(fourth.get());
    134 
    135   scoped_ptr<WindowListProvider> list_provider(
    136       new WindowListProviderImpl(container.get()));
    137 
    138   const aura::Window::Windows& list = list_provider->GetWindowList();
    139   EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), second.get()));
    140   EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), fourth.get()));
    141   EXPECT_NE(list.end(), std::find(list.begin(), list.end(), first.get()));
    142   EXPECT_NE(list.end(), std::find(list.begin(), list.end(), third.get()));
    143 }
    144 
    145 // Testing that IsValidWidow, IsWindowInList and AddWindow work as expected.
    146 TEST_F(WindowListProviderImplTest, SimpleChecks) {
    147   aura::test::TestWindowDelegate delegate;
    148   scoped_ptr<aura::Window> container(new aura::Window(&delegate));
    149 
    150   scoped_ptr<aura::Window> normal_window =
    151       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    152   scoped_ptr<aura::Window> popup_window =
    153       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP);
    154   scoped_ptr<aura::Window> menu_window =
    155       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU);
    156 
    157   scoped_ptr<WindowListProvider> list_provider(
    158       new WindowListProviderImpl(container.get()));
    159 
    160   // Check which windows are valid and which are not.
    161   EXPECT_TRUE(list_provider->IsValidWindow(normal_window.get()));
    162   EXPECT_FALSE(list_provider->IsValidWindow(popup_window.get()));
    163   EXPECT_FALSE(list_provider->IsValidWindow(menu_window.get()));
    164 
    165   // Check that no window is currently in the list.
    166   EXPECT_FALSE(list_provider->IsWindowInList(normal_window.get()));
    167   EXPECT_FALSE(list_provider->IsWindowInList(popup_window.get()));
    168   EXPECT_FALSE(list_provider->IsWindowInList(menu_window.get()));
    169 
    170   // Check that adding the window will add it to the list.
    171   container->AddChild(normal_window.get());
    172   EXPECT_TRUE(list_provider->IsWindowInList(normal_window.get()));
    173 }
    174 
    175 // Testing that window ordering functions work as expected.
    176 TEST_F(WindowListProviderImplTest, TestWindowOrderingFunctions) {
    177   aura::test::TestWindowDelegate delegate;
    178   scoped_ptr<aura::Window> container(new aura::Window(&delegate));
    179 
    180   scoped_ptr<aura::Window> window1 =
    181       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    182   scoped_ptr<aura::Window> window2 =
    183       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    184   scoped_ptr<aura::Window> window3 =
    185       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    186 
    187   scoped_ptr<WindowListProvider> list_provider(
    188       new WindowListProviderImpl(container.get()));
    189   scoped_ptr<WindowListObserver> observer(
    190       new WindowListObserver(list_provider.get()));
    191 
    192   EXPECT_FALSE(list_provider->IsWindowInList(window1.get()));
    193   EXPECT_FALSE(list_provider->IsWindowInList(window2.get()));
    194   EXPECT_FALSE(list_provider->IsWindowInList(window3.get()));
    195 
    196   // Add the windows.
    197   container->AddChild(window1.get());
    198   container->AddChild(window2.get());
    199   container->AddChild(window3.get());
    200   // Make a copy of the window-list in the original order.
    201   aura::Window::Windows original_order = list_provider->GetWindowList();
    202   ASSERT_EQ(3U, original_order.size());
    203   EXPECT_EQ(original_order[0], window1.get());
    204   EXPECT_EQ(original_order[1], window2.get());
    205   EXPECT_EQ(original_order[2], window3.get());
    206 
    207   EXPECT_EQ(0, observer.get()->calls());
    208 
    209   // Move 1 (from the back) in front of 2.
    210   list_provider->StackWindowFrontOf(window1.get(), window2.get());
    211   EXPECT_EQ("2 1 3", GetWindowOrder(original_order,
    212                                     list_provider->GetWindowList()));
    213   EXPECT_EQ(1, observer->calls());
    214 
    215   // Move 3 (from the front) in front of 2.
    216   list_provider->StackWindowFrontOf(window3.get(), window2.get());
    217   EXPECT_EQ("2 3 1", GetWindowOrder(original_order,
    218                                     list_provider->GetWindowList()));
    219   EXPECT_EQ(2, observer->calls());
    220 
    221   // Move 1 (from the front) behind 2.
    222   list_provider->StackWindowBehindTo(window1.get(), window2.get());
    223   EXPECT_EQ("1 2 3", GetWindowOrder(original_order,
    224                                     list_provider->GetWindowList()));
    225   EXPECT_EQ(3, observer->calls());
    226 
    227   // Move 1 (from the back) in front of 3.
    228   list_provider->StackWindowFrontOf(window1.get(), window3.get());
    229   EXPECT_EQ("2 3 1", GetWindowOrder(original_order,
    230                                     list_provider->GetWindowList()));
    231   EXPECT_EQ(4, observer->calls());
    232 
    233   // Test that no change should also report no call.
    234   list_provider->StackWindowFrontOf(window1.get(), window3.get());
    235   EXPECT_EQ("2 3 1", GetWindowOrder(original_order,
    236                                     list_provider->GetWindowList()));
    237   EXPECT_EQ(4, observer->calls());
    238   list_provider->StackWindowBehindTo(window3.get(), window1.get());
    239   EXPECT_EQ("2 3 1", GetWindowOrder(original_order,
    240                                     list_provider->GetWindowList()));
    241   EXPECT_EQ(4, observer->calls());
    242 }
    243 
    244 TEST_F(WindowListProviderImplTest, TestWindowRemovalNotification) {
    245   aura::test::TestWindowDelegate delegate;
    246   scoped_ptr<aura::Window> container(new aura::Window(&delegate));
    247 
    248   scoped_ptr<aura::Window> window1 =
    249       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    250   scoped_ptr<aura::Window> window2 =
    251       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    252   scoped_ptr<aura::Window> window3 =
    253       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL);
    254   scoped_ptr<aura::Window> window4 =
    255       CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP);
    256 
    257   scoped_ptr<WindowListProvider> list_provider(
    258       new WindowListProviderImpl(container.get()));
    259   scoped_ptr<WindowListObserver> observer(
    260       new WindowListObserver(list_provider.get()));
    261 
    262   // Add the windows.
    263   container->AddChild(window1.get());
    264   container->AddChild(window2.get());
    265   container->AddChild(window3.get());
    266   container->AddChild(window4.get());
    267   // The popup-window (window4) should not be included in the window-list.
    268   ASSERT_EQ(3U, list_provider->GetWindowList().size());
    269   EXPECT_EQ(0, observer->window_removal_calls());
    270   EXPECT_FALSE(list_provider->IsWindowInList(window4.get()));
    271 
    272   // Destroying the popup window should not trigger the remove notification.
    273   window4.reset();
    274   ASSERT_EQ(3U, list_provider->GetWindowList().size());
    275   EXPECT_EQ(0, observer->window_removal_calls());
    276 
    277   window2.reset();
    278   ASSERT_EQ(2U, list_provider->GetWindowList().size());
    279   EXPECT_EQ(1, observer->window_removal_calls());
    280 
    281   window1.reset();
    282   ASSERT_EQ(1U, list_provider->GetWindowList().size());
    283   EXPECT_EQ(2, observer->window_removal_calls());
    284 
    285   window3.reset();
    286   ASSERT_EQ(0U, list_provider->GetWindowList().size());
    287   EXPECT_EQ(3, observer->window_removal_calls());
    288 }
    289 
    290 }  // namespace athena
    291