chromium/chromecast/graphics/cast_focus_client_aura_test.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromecast/graphics/cast_focus_client_aura.h"

#include <memory>

#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace chromecast {
namespace test {
namespace {

class TestWindow {
 public:
  TestWindow() : window_(&delegate_) {
    window_.Init(ui::LAYER_NOT_DRAWN);
    window_.Show();
  }

  TestWindow(const TestWindow&) = delete;
  TestWindow& operator=(const TestWindow&) = delete;

  aura::test::TestWindowDelegate* delegate() { return &delegate_; }
  aura::Window* window() { return &window_; }

 private:
  aura::test::TestWindowDelegate delegate_;
  aura::Window window_;
};

}  // namespace

using CastFocusClientAuraTest = aura::test::AuraTestBase;

TEST_F(CastFocusClientAuraTest, FocusableWindows) {
  std::unique_ptr<aura::WindowTreeHost> window_tree_host =
      aura::WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 1280, 720)});
  window_tree_host->InitHost();
  window_tree_host->Show();

  CastFocusClientAura focus_client;

  std::unique_ptr<TestWindow> test_window(new TestWindow);
  window_tree_host->window()->AddChild(test_window->window());

  // Confirm that we can't add an un-focusable window.
  test_window->delegate()->set_can_focus(false);
  focus_client.FocusWindow(test_window->window());
  EXPECT_FALSE(focus_client.GetFocusedWindow());

  // Confirm that we can add a focusable window.
  test_window->delegate()->set_can_focus(true);
  focus_client.FocusWindow(test_window->window());
  EXPECT_EQ(test_window->window(), focus_client.GetFocusedWindow());

  // Confirm that the focused window loses focus when losing visibility.
  test_window->window()->Hide();
  EXPECT_FALSE(focus_client.GetFocusedWindow());

  // Confirm that we find a focusable window when it becomes visible.
  test_window->window()->Show();
  EXPECT_EQ(test_window->window(), focus_client.GetFocusedWindow());

  // Confirm that the focused window loses focus when it is destroyed.
  test_window.reset();
  EXPECT_FALSE(focus_client.GetFocusedWindow());
}

TEST_F(CastFocusClientAuraTest, ChildFocus) {
  std::unique_ptr<aura::WindowTreeHost> window_tree_host =
      aura::WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 1280, 720)});
  window_tree_host->InitHost();
  window_tree_host->Show();

  CastFocusClientAura focus_client;

  std::unique_ptr<TestWindow> parent(new TestWindow);
  parent->delegate()->set_can_focus(true);
  window_tree_host->window()->AddChild(parent->window());

  std::unique_ptr<TestWindow> child(new TestWindow);
  child->delegate()->set_can_focus(true);
  parent->window()->AddChild(child->window());

  // Confirm that the child window has the focus, not its top-level parent
  // window.
  focus_client.FocusWindow(child->window());
  EXPECT_EQ(child->window(), focus_client.GetFocusedWindow());

  // Confirm that removing the child window doesn't focus the parent window
  // (since we've never requested focus for the parent window).
  parent->window()->RemoveChild(child->window());
  EXPECT_FALSE(focus_client.GetFocusedWindow());

  // Confirm that we still have no focused window after re-adding the child
  // window, because we haven't requested focus.
  parent->window()->AddChild(child->window());
  EXPECT_FALSE(focus_client.GetFocusedWindow());

  // Request focus and confirm that the child is focused.
  focus_client.FocusWindow(child->window());
  EXPECT_EQ(child->window(), focus_client.GetFocusedWindow());
}

TEST_F(CastFocusClientAuraTest, ZOrder) {
  std::unique_ptr<aura::WindowTreeHost> window_tree_host =
      aura::WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 1280, 720)});
  window_tree_host->InitHost();
  window_tree_host->Show();

  CastFocusClientAura focus_client;

  // Add the window with the lowest z-order.
  std::unique_ptr<TestWindow> low(new TestWindow);
  low->delegate()->set_can_focus(true);
  low->window()->SetId(1);
  window_tree_host->window()->AddChild(low->window());
  focus_client.FocusWindow(low->window());
  EXPECT_EQ(low->window(), focus_client.GetFocusedWindow());

  // Add the window with the highest z-order, and confirm that it gets focus.
  std::unique_ptr<TestWindow> high(new TestWindow);
  high->delegate()->set_can_focus(true);
  high->window()->SetId(3);
  window_tree_host->window()->AddChild(high->window());
  focus_client.FocusWindow(high->window());
  EXPECT_EQ(high->window(), focus_client.GetFocusedWindow());

  // Add the window with the middle z-order, and confirm that focus remains with
  // the highest z-order window.
  std::unique_ptr<TestWindow> middle(new TestWindow);
  middle->delegate()->set_can_focus(true);
  middle->window()->SetId(2);
  window_tree_host->window()->AddChild(middle->window());
  focus_client.FocusWindow(middle->window());
  EXPECT_EQ(high->window(), focus_client.GetFocusedWindow());

  // Confirm that requesting focus on the lower z-order windows leaves focus on
  // the highest z-order window.
  focus_client.FocusWindow(low->window());
  EXPECT_EQ(high->window(), focus_client.GetFocusedWindow());
  focus_client.FocusWindow(middle->window());
  EXPECT_EQ(high->window(), focus_client.GetFocusedWindow());

  // Confirm that focus moves to next highest window.
  high.reset();
  EXPECT_EQ(middle->window(), focus_client.GetFocusedWindow());

  // Confirm that focus moves to next highest window.
  middle.reset();
  EXPECT_EQ(low->window(), focus_client.GetFocusedWindow());

  // Confirm that there is no focused window.
  low.reset();
  EXPECT_FALSE(focus_client.GetFocusedWindow());
}

TEST_F(CastFocusClientAuraTest, ZOrderWithChildWindows) {
  std::unique_ptr<aura::WindowTreeHost> window_tree_host =
      aura::WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 1280, 720)});
  window_tree_host->InitHost();
  window_tree_host->Show();

  CastFocusClientAura focus_client;

  // Add the window with the highest z-order.
  std::unique_ptr<TestWindow> high_parent(new TestWindow);
  high_parent->window()->SetId(3);
  std::unique_ptr<TestWindow> high_child(new TestWindow);
  high_child->delegate()->set_can_focus(true);
  high_parent->window()->AddChild(high_child->window());
  window_tree_host->window()->AddChild(high_parent->window());
  focus_client.FocusWindow(high_child->window());
  EXPECT_EQ(high_child->window(), focus_client.GetFocusedWindow());

  // Add the window with the lowest z-order.
  std::unique_ptr<TestWindow> low_parent(new TestWindow);
  low_parent->window()->SetId(1);
  std::unique_ptr<TestWindow> low_child(new TestWindow);
  low_child->delegate()->set_can_focus(true);
  low_parent->window()->AddChild(low_child->window());
  window_tree_host->window()->AddChild(low_parent->window());
  focus_client.FocusWindow(low_child->window());
  // Focus should remain with the child of the highest window.
  EXPECT_EQ(high_child->window(), focus_client.GetFocusedWindow());
}

}  // namespace test
}  // namespace chromecast