// Copyright (c) 2013 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 "ui/aura/window_targeter.h"

#include <utility>

#include "base/macros.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/test_event_handler.h"

namespace aura {

// Always returns the same window.
class StaticWindowTargeter : public WindowTargeter {
 public:
  explicit StaticWindowTargeter(aura::Window* window)
      : window_(window) {}
  ~StaticWindowTargeter() override {}

 private:
  // aura::WindowTargeter:
  Window* FindTargetForLocatedEvent(Window* window,
                                    ui::LocatedEvent* event) override {
    return window_;
  }

  Window* window_;

  DISALLOW_COPY_AND_ASSIGN(StaticWindowTargeter);
};

gfx::RectF GetEffectiveVisibleBoundsInRootWindow(Window* window) {
  gfx::RectF bounds = gfx::RectF(gfx::SizeF(window->bounds().size()));
  Window* root = window->GetRootWindow();
  CHECK(window->layer());
  CHECK(root->layer());
  gfx::Transform transform;
  if (!window->layer()->GetTargetTransformRelativeTo(root->layer(), &transform))
    return gfx::RectF();
  transform.TransformRect(&bounds);
  return bounds;
}

using WindowTargeterTest = test::AuraTestBase;

TEST_F(WindowTargeterTest, Basic) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> window(
      CreateNormalWindow(1, root_window(), &delegate));
  Window* one = CreateNormalWindow(2, window.get(), &delegate);
  Window* two = CreateNormalWindow(3, window.get(), &delegate);

  window->SetBounds(gfx::Rect(0, 0, 1000, 1000));
  one->SetBounds(gfx::Rect(0, 0, 500, 100));
  two->SetBounds(gfx::Rect(501, 0, 500, 1000));

  root_window()->Show();

  ui::test::TestEventHandler handler;
  one->AddPreTargetHandler(&handler);

  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(20, 20),
                       gfx::Point(20, 20), ui::EventTimeForNow(), ui::EF_NONE,
                       ui::EF_NONE);
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_EQ(1, handler.num_mouse_events());

  handler.Reset();
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_EQ(1, handler.num_mouse_events());

  one->RemovePreTargetHandler(&handler);
}

TEST_F(WindowTargeterTest, FindTargetInRootWindow) {
  WindowTargeter targeter;

  display::Display display =
      display::Screen::GetScreen()->GetDisplayNearestWindow(root_window());
  EXPECT_EQ(display.bounds(), root_window()->GetBoundsInScreen());
  EXPECT_EQ(display.bounds(), gfx::Rect(0, 0, 800, 600));

  // Mouse and touch presses inside the display yield null targets.
  gfx::Point inside = display.bounds().CenterPoint();
  ui::MouseEvent mouse1(ui::ET_MOUSE_PRESSED, inside, inside,
                        ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  ui::TouchEvent touch1(ui::ET_TOUCH_PRESSED, inside, ui::EventTimeForNow(),
                        ui::PointerDetails());
  touch1.set_root_location(inside);
  EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), mouse1));
  EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), touch1));

  // Touch presses outside the display yields the root window as a target.
  gfx::Point outside(display.bounds().right() + 10, inside.y());
  ui::MouseEvent mouse2(ui::ET_MOUSE_PRESSED, outside, outside,
                        ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  ui::TouchEvent touch2(ui::ET_TOUCH_PRESSED, outside, ui::EventTimeForNow(),
                        ui::PointerDetails());
  touch2.set_root_location(outside);
  EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), mouse2));
  EXPECT_EQ(root_window(),
            targeter.FindTargetInRootWindow(root_window(), touch2));
}

TEST_F(WindowTargeterTest, ScopedWindowTargeter) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> window(
      CreateNormalWindow(1, root_window(), &delegate));
  Window* child = CreateNormalWindow(2, window.get(), &delegate);

  window->SetBounds(gfx::Rect(30, 30, 100, 100));
  child->SetBounds(gfx::Rect(20, 20, 50, 50));
  root_window()->Show();

  ui::EventTarget* root = root_window();
  ui::EventTargeter* targeter = root->GetEventTargeter();

  gfx::Point event_location(60, 60);
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
  }

  // Install a targeter on |window| so that the events never reach the child.
  std::unique_ptr<ScopedWindowTargeter> scoped_targeter(
      new ScopedWindowTargeter(window.get(),
                               std::unique_ptr<WindowTargeter>(
                                   new StaticWindowTargeter(window.get()))));
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse));
  }
  scoped_targeter.reset();
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
  }
}

// Test that ScopedWindowTargeter does not crash if the window for which it
// replaces the targeter gets destroyed before it does.
TEST_F(WindowTargeterTest, ScopedWindowTargeterWindowDestroyed) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> window(
      CreateNormalWindow(1, root_window(), &delegate));
  std::unique_ptr<ScopedWindowTargeter> scoped_targeter(
      new ScopedWindowTargeter(window.get(),
                               std::unique_ptr<aura::WindowTargeter>(
                                   new StaticWindowTargeter(window.get()))));

  window.reset();
  scoped_targeter.reset();

  // We did not crash!
}

TEST_F(WindowTargeterTest, TargetTransformedWindow) {
  root_window()->Show();

  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> window(
      CreateNormalWindow(2, root_window(), &delegate));

  const gfx::Rect window_bounds(100, 20, 400, 80);
  window->SetBounds(window_bounds);

  ui::EventTarget* root_target = root_window();
  ui::EventTargeter* targeter = root_target->GetEventTargeter();
  gfx::Point event_location(490, 50);
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
  }

  // Scale |window| by 50%. This should move it away from underneath
  // |event_location|, so an event in that location will not be targeted to it.
  gfx::Transform transform;
  transform.Scale(0.5, 0.5);
  window->SetTransform(transform);
  EXPECT_EQ(gfx::RectF(100, 20, 200, 40).ToString(),
            GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(root_window(), targeter->FindTargetForEvent(root_target, &mouse));
  }

  transform = gfx::Transform();
  transform.Translate(200, 10);
  transform.Scale(0.5, 0.5);
  window->SetTransform(transform);
  EXPECT_EQ(gfx::RectF(300, 30, 200, 40).ToString(),
            GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
  }
}

class IdCheckingEventTargeter : public WindowTargeter {
 public:
  explicit IdCheckingEventTargeter(int id) : id_(id) {}
  ~IdCheckingEventTargeter() override {}

 protected:
  // WindowTargeter:
  bool SubtreeShouldBeExploredForEvent(Window* window,
                                       const ui::LocatedEvent& event) override {
    return (window->id() == id_ &&
            WindowTargeter::SubtreeShouldBeExploredForEvent(window, event));
  }

 private:
  int id_;
};

TEST_F(WindowTargeterTest, Bounds) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> parent(
      CreateNormalWindow(1, root_window(), &delegate));
  std::unique_ptr<Window> child(CreateNormalWindow(1, parent.get(), &delegate));
  std::unique_ptr<Window> grandchild(
      CreateNormalWindow(1, child.get(), &delegate));

  parent->SetBounds(gfx::Rect(0, 0, 30, 30));
  child->SetBounds(gfx::Rect(5, 5, 20, 20));
  grandchild->SetBounds(gfx::Rect(5, 5, 5, 5));

  ASSERT_EQ(1u, root_window()->children().size());
  ASSERT_EQ(1u, root_window()->children()[0]->children().size());
  ASSERT_EQ(1u, root_window()->children()[0]->children()[0]->children().size());

  Window* parent_r = root_window()->children()[0];
  Window* child_r = parent_r->children()[0];
  Window* grandchild_r = child_r->children()[0];

  ui::EventTarget* root_target = root_window();
  ui::EventTargeter* targeter = root_target->GetEventTargeter();

  // Dispatch a mouse event that falls on the parent, but not on the child. When
  // the default event-targeter used, the event will still reach |grandchild|,
  // because the default targeter does not look at the bounds.
  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(1, 1),
                       ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  EXPECT_EQ(parent_r, targeter->FindTargetForEvent(root_target, &mouse));

  // Install a targeter on the |child| that looks at the window id as well
  // as the bounds and makes sure the event reaches the target only if the id of
  // the window is equal to 2 (incorrect). This causes the event to get handled
  // by |parent|.
  ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(8, 8), gfx::Point(8, 8),
                        ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  std::unique_ptr<aura::WindowTargeter> original_targeter =
      child_r->SetEventTargeter(std::make_unique<IdCheckingEventTargeter>(2));
  EXPECT_EQ(parent_r, targeter->FindTargetForEvent(root_target, &mouse2));

  // Now install a targeter on the |child| that looks at the window id as well
  // as the bounds and makes sure the event reaches the target only if the id of
  // the window is equal to 1 (correct).
  ui::MouseEvent mouse3(ui::ET_MOUSE_MOVED, gfx::Point(8, 8), gfx::Point(8, 8),
                        ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  child_r->SetEventTargeter(std::make_unique<IdCheckingEventTargeter>(1));
  EXPECT_EQ(child_r, targeter->FindTargetForEvent(root_target, &mouse3));

  // restore original WindowTargeter for |child|.
  child_r->SetEventTargeter(std::move(original_targeter));

  // Target |grandchild| location.
  ui::MouseEvent second(ui::ET_MOUSE_MOVED, gfx::Point(12, 12),
                        gfx::Point(12, 12), ui::EventTimeForNow(), ui::EF_NONE,
                        ui::EF_NONE);
  EXPECT_EQ(grandchild_r, targeter->FindTargetForEvent(root_target, &second));

  // Target |child| location.
  ui::MouseEvent third(ui::ET_MOUSE_MOVED, gfx::Point(8, 8), gfx::Point(8, 8),
                       ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
  EXPECT_EQ(child_r, targeter->FindTargetForEvent(root_target, &third));
}

class IgnoreWindowTargeter : public WindowTargeter {
 public:
  IgnoreWindowTargeter() {}
  ~IgnoreWindowTargeter() override {}

 private:
  // WindowTargeter:
  bool SubtreeShouldBeExploredForEvent(Window* window,
                                       const ui::LocatedEvent& event) override {
    return false;
  }
};

// Verifies that an EventTargeter installed on an EventTarget can dictate
// whether the target itself can process an event.
TEST_F(WindowTargeterTest, TargeterChecksOwningEventTarget) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> child(
      CreateNormalWindow(1, root_window(), &delegate));

  ui::EventTarget* root_target = root_window();
  ui::EventTargeter* targeter = root_target->GetEventTargeter();

  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                       gfx::Point(10, 10), ui::EventTimeForNow(), ui::EF_NONE,
                       ui::EF_NONE);
  EXPECT_EQ(child.get(), targeter->FindTargetForEvent(root_target, &mouse));

  // Install an event targeter on |child| which always prevents the target from
  // receiving event.
  child->SetEventTargeter(std::make_unique<IgnoreWindowTargeter>());

  ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeForNow(), ui::EF_NONE,
                        ui::EF_NONE);
  EXPECT_EQ(root_window(), targeter->FindTargetForEvent(root_target, &mouse2));
}

}  // namespace aura
