// 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 "ui/aura/window_event_dispatcher.h"

#include <stddef.h>

#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/env.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/env_test_helper.h"
#include "ui/aura/test/test_cursor_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_features.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/test/event_generator.h"
#include "ui/events/test/test_event_handler.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/transform.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace aura {
namespace {

// A delegate that always returns a non-client component for hit tests.
class NonClientDelegate : public test::TestWindowDelegate {
 public:
  NonClientDelegate()
      : non_client_count_(0),
        mouse_event_count_(0),
        mouse_event_flags_(0x0) {
  }
  ~NonClientDelegate() override {}

  int non_client_count() const { return non_client_count_; }
  const gfx::Point& non_client_location() const { return non_client_location_; }
  int mouse_event_count() const { return mouse_event_count_; }
  const gfx::Point& mouse_event_location() const {
    return mouse_event_location_;
  }
  int mouse_event_flags() const { return mouse_event_flags_; }

  int GetNonClientComponent(const gfx::Point& location) const override {
    NonClientDelegate* self = const_cast<NonClientDelegate*>(this);
    self->non_client_count_++;
    self->non_client_location_ = location;
    return HTMENU;
  }
  void OnMouseEvent(ui::MouseEvent* event) override {
    mouse_event_count_++;
    mouse_event_location_ = event->location();
    mouse_event_flags_ = event->flags();
    event->SetHandled();
  }

 private:
  int non_client_count_;
  gfx::Point non_client_location_;
  int mouse_event_count_;
  gfx::Point mouse_event_location_;
  int mouse_event_flags_;

  DISALLOW_COPY_AND_ASSIGN(NonClientDelegate);
};

// A simple event handler that consumes key events.
class ConsumeKeyHandler : public ui::test::TestEventHandler {
 public:
  ConsumeKeyHandler() {}
  ~ConsumeKeyHandler() override {}

  // Overridden from ui::EventHandler:
  void OnKeyEvent(ui::KeyEvent* event) override {
    ui::test::TestEventHandler::OnKeyEvent(event);
    event->StopPropagation();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ConsumeKeyHandler);
};

bool IsFocusedWindow(aura::Window* window) {
  return client::GetFocusClient(window)->GetFocusedWindow() == window;
}

}  // namespace

using WindowEventDispatcherTest = test::AuraTestBase;

TEST_F(WindowEventDispatcherTest, OnHostMouseEvent) {
  // Create two non-overlapping windows so we don't have to worry about which
  // is on top.
  std::unique_ptr<NonClientDelegate> delegate1(new NonClientDelegate());
  std::unique_ptr<NonClientDelegate> delegate2(new NonClientDelegate());
  const int kWindowWidth = 123;
  const int kWindowHeight = 45;
  gfx::Rect bounds1(100, 200, kWindowWidth, kWindowHeight);
  gfx::Rect bounds2(300, 400, kWindowWidth, kWindowHeight);
  std::unique_ptr<aura::Window> window1(CreateTestWindowWithDelegate(
      delegate1.get(), -1234, bounds1, root_window()));
  std::unique_ptr<aura::Window> window2(CreateTestWindowWithDelegate(
      delegate2.get(), -5678, bounds2, root_window()));

  // Send a mouse event to window1.
  gfx::Point point(101, 201);
  ui::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, point,
                        ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                        ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&event1);

  // Event was tested for non-client area for the target window.
  EXPECT_EQ(1, delegate1->non_client_count());
  EXPECT_EQ(0, delegate2->non_client_count());
  // The non-client component test was in local coordinates.
  EXPECT_EQ(gfx::Point(1, 1), delegate1->non_client_location());
  // Mouse event was received by target window.
  EXPECT_EQ(1, delegate1->mouse_event_count());
  EXPECT_EQ(0, delegate2->mouse_event_count());
  // Event was in local coordinates.
  EXPECT_EQ(gfx::Point(1, 1), delegate1->mouse_event_location());
  // Non-client flag was set.
  EXPECT_TRUE(delegate1->mouse_event_flags() & ui::EF_IS_NON_CLIENT);
}

TEST_F(WindowEventDispatcherTest, RepostEvent) {
  // Test RepostEvent in RootWindow. It only works for Mouse Press and touch
  // press.
  EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
  gfx::Point point(10, 10);
  ui::MouseEvent event(ui::ET_MOUSE_PRESSED, point, point,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  host()->dispatcher()->RepostEvent(&event);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());

  ui::TouchEvent touch_pressed_event(
      ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  host()->dispatcher()->RepostEvent(&touch_pressed_event);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(Env::GetInstance()->is_touch_down());
}

// Check that we correctly track whether any touch devices are down in response
// to touch press and release events with two WindowTreeHost.
TEST_F(WindowEventDispatcherTest, TouchDownState) {
  std::unique_ptr<WindowTreeHost> second_host = WindowTreeHost::Create(
      ui::PlatformWindowInitProperties{gfx::Rect(20, 30, 100, 50)});
  second_host->InitHost();
  second_host->window()->Show();

  ui::TouchEvent touch_pressed_event1(
      ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1));
  ui::TouchEvent touch_pressed_event2(
      ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2));
  ui::TouchEvent touch_released_event1(
      ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1));
  ui::TouchEvent touch_released_event2(
      ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2));

  EXPECT_FALSE(Env::GetInstance()->is_touch_down());
  host()->dispatcher()->OnEventFromSource(&touch_pressed_event1);
  EXPECT_TRUE(Env::GetInstance()->is_touch_down());
  second_host->dispatcher()->OnEventFromSource(&touch_pressed_event2);
  EXPECT_TRUE(Env::GetInstance()->is_touch_down());
  host()->dispatcher()->OnEventFromSource(&touch_released_event1);
  EXPECT_TRUE(Env::GetInstance()->is_touch_down());
  second_host->dispatcher()->OnEventFromSource(&touch_released_event2);
  EXPECT_FALSE(Env::GetInstance()->is_touch_down());
}

// Check that we correctly track the state of the mouse buttons in response to
// button press and release events.
TEST_F(WindowEventDispatcherTest, MouseButtonState) {
  EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());

  gfx::Point location;
  std::unique_ptr<ui::MouseEvent> event;

  // Press the left button.
  event.reset(new ui::MouseEvent(
      ui::ET_MOUSE_PRESSED, location, location, ui::EventTimeForNow(),
      ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
  DispatchEventUsingWindowDispatcher(event.get());
  EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());

  // Additionally press the right.
  event.reset(new ui::MouseEvent(
      ui::ET_MOUSE_PRESSED, location, location, ui::EventTimeForNow(),
      ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
      ui::EF_RIGHT_MOUSE_BUTTON));
  DispatchEventUsingWindowDispatcher(event.get());
  EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());

  // Release the left button.
  event.reset(new ui::MouseEvent(
      ui::ET_MOUSE_RELEASED, location, location, ui::EventTimeForNow(),
      ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
  DispatchEventUsingWindowDispatcher(event.get());
  EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());

  // Release the right button.  We should ignore the Shift-is-down flag.
  event.reset(new ui::MouseEvent(ui::ET_MOUSE_RELEASED, location, location,
                                 ui::EventTimeForNow(), ui::EF_SHIFT_DOWN,
                                 ui::EF_RIGHT_MOUSE_BUTTON));
  DispatchEventUsingWindowDispatcher(event.get());
  EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());

  // Press the middle button.
  event.reset(new ui::MouseEvent(
      ui::ET_MOUSE_PRESSED, location, location, ui::EventTimeForNow(),
      ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON));
  DispatchEventUsingWindowDispatcher(event.get());
  EXPECT_TRUE(Env::GetInstance()->IsMouseButtonDown());
}

TEST_F(WindowEventDispatcherTest, TranslatedEvent) {
  std::unique_ptr<Window> w1(test::CreateTestWindowWithDelegate(
      NULL, 1, gfx::Rect(50, 50, 100, 100), root_window()));

  gfx::Point origin(100, 100);
  ui::MouseEvent root(ui::ET_MOUSE_PRESSED, origin, origin,
                      ui::EventTimeForNow(), 0, 0);

  EXPECT_EQ("100,100", root.location().ToString());
  EXPECT_EQ("100,100", root.root_location().ToString());

  ui::MouseEvent translated_event(
      root, static_cast<Window*>(root_window()), w1.get(),
      ui::ET_MOUSE_ENTERED, root.flags());
  EXPECT_EQ("50,50", translated_event.location().ToString());
  EXPECT_EQ("100,100", translated_event.root_location().ToString());
}

namespace {

class TestEventClient : public client::EventClient {
 public:
  static const int kNonLockWindowId = 100;
  static const int kLockWindowId = 200;

  explicit TestEventClient(Window* root_window)
      : root_window_(root_window),
        lock_(false) {
    client::SetEventClient(root_window_, this);
    Window* lock_window =
        test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
    lock_window->set_id(kLockWindowId);
    Window* non_lock_window =
        test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
    non_lock_window->set_id(kNonLockWindowId);
  }
  ~TestEventClient() override { client::SetEventClient(root_window_, NULL); }

  // Starts/stops locking. Locking prevents windows other than those inside
  // the lock container from receiving events, getting focus etc.
  void Lock() {
    lock_ = true;
  }
  void Unlock() {
    lock_ = false;
  }

  Window* GetLockWindow() {
    return const_cast<Window*>(
        static_cast<const TestEventClient*>(this)->GetLockWindow());
  }
  const Window* GetLockWindow() const {
    return root_window_->GetChildById(kLockWindowId);
  }
  Window* GetNonLockWindow() {
    return root_window_->GetChildById(kNonLockWindowId);
  }

 private:
  // Overridden from client::EventClient:
  bool CanProcessEventsWithinSubtree(const Window* window) const override {
    return lock_ ?
        window->Contains(GetLockWindow()) || GetLockWindow()->Contains(window) :
        true;
  }

  ui::EventTarget* GetToplevelEventTarget() override { return NULL; }

  Window* root_window_;
  bool lock_;

  DISALLOW_COPY_AND_ASSIGN(TestEventClient);
};

}  // namespace

TEST_F(WindowEventDispatcherTest, CanProcessEventsWithinSubtree) {
  TestEventClient client(root_window());
  test::TestWindowDelegate d;

  ui::test::TestEventHandler nonlock_ef;
  ui::test::TestEventHandler lock_ef;
  client.GetNonLockWindow()->AddPreTargetHandler(&nonlock_ef);
  client.GetLockWindow()->AddPreTargetHandler(&lock_ef);

  Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20),
                                                client.GetNonLockWindow());
  w1->set_id(1);
  Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20),
                                                client.GetNonLockWindow());
  w2->set_id(2);
  std::unique_ptr<Window> w3(test::CreateTestWindowWithDelegate(
      &d, 3, gfx::Rect(30, 30, 20, 20), client.GetLockWindow()));

  w1->Focus();
  EXPECT_TRUE(IsFocusedWindow(w1));

  client.Lock();

  // Since we're locked, the attempt to focus w2 will be ignored.
  w2->Focus();
  EXPECT_TRUE(IsFocusedWindow(w1));
  EXPECT_FALSE(IsFocusedWindow(w2));

  {
    // Attempting to send a key event to w1 (not in the lock container) should
    // cause focus to be reset.
    ui::test::EventGenerator generator(root_window());
    generator.PressKey(ui::VKEY_SPACE, 0);
    EXPECT_EQ(NULL, client::GetFocusClient(w1)->GetFocusedWindow());
    EXPECT_FALSE(IsFocusedWindow(w1));
  }

  {
    // Events sent to a window not in the lock container will not be processed.
    // i.e. never sent to the non-lock container's event filter.
    ui::test::EventGenerator generator(root_window(), w1);
    generator.ClickLeftButton();
    EXPECT_EQ(0, nonlock_ef.num_mouse_events());

    // Events sent to a window in the lock container will be processed.
    ui::test::EventGenerator generator3(root_window(), w3.get());
    generator3.PressLeftButton();
    EXPECT_EQ(1, lock_ef.num_mouse_events());
  }

  // Prevent w3 from being deleted by the hierarchy since its delegate is owned
  // by this scope.
  w3->parent()->RemoveChild(w3.get());

  client.GetNonLockWindow()->RemovePreTargetHandler(&nonlock_ef);
  client.GetLockWindow()->RemovePreTargetHandler(&lock_ef);
}

TEST_F(WindowEventDispatcherTest, DontIgnoreUnknownKeys) {
  ConsumeKeyHandler handler;
  root_window()->AddPreTargetHandler(&handler);

  ui::KeyEvent unknown_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_NONE);
  DispatchEventUsingWindowDispatcher(&unknown_event);
  EXPECT_TRUE(unknown_event.handled());
  EXPECT_EQ(1, handler.num_key_events());

  handler.Reset();
  ui::KeyEvent known_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
  DispatchEventUsingWindowDispatcher(&known_event);
  EXPECT_TRUE(known_event.handled());
  EXPECT_EQ(1, handler.num_key_events());

  handler.Reset();
  ui::KeyEvent ime_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
                         ui::EF_IME_FABRICATED_KEY);
  DispatchEventUsingWindowDispatcher(&ime_event);
  EXPECT_TRUE(ime_event.handled());
  EXPECT_EQ(1, handler.num_key_events());

  handler.Reset();
  ui::KeyEvent unknown_key_with_char_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN,
                                           ui::EF_NONE);
  unknown_key_with_char_event.set_character(0x00e4 /* "ä" */);
  DispatchEventUsingWindowDispatcher(&unknown_key_with_char_event);
  EXPECT_TRUE(unknown_key_with_char_event.handled());
  EXPECT_EQ(1, handler.num_key_events());
  root_window()->RemovePreTargetHandler(&handler);
}

TEST_F(WindowEventDispatcherTest, NoDelegateWindowReceivesKeyEvents) {
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
  w1->Show();
  w1->Focus();

  ui::test::TestEventHandler handler;
  w1->AddPreTargetHandler(&handler);
  ui::KeyEvent key_press(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
  DispatchEventUsingWindowDispatcher(&key_press);
  EXPECT_TRUE(key_press.handled());
  EXPECT_EQ(1, handler.num_key_events());

  w1->RemovePreTargetHandler(&handler);
}

// Tests that touch-events that are beyond the bounds of the root-window do get
// propagated to the event filters correctly with the root as the target.
TEST_F(WindowEventDispatcherTest, TouchEventsOutsideBounds) {
  ui::test::TestEventHandler handler;
  root_window()->AddPreTargetHandler(&handler);

  gfx::Point position = root_window()->bounds().origin();
  position.Offset(-10, -10);
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, position, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_EQ(1, handler.num_touch_events());

  position = root_window()->bounds().origin();
  position.Offset(root_window()->bounds().width() + 10,
                  root_window()->bounds().height() + 10);
  ui::TouchEvent release(
      ui::ET_TOUCH_RELEASED, position, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&release);
  EXPECT_EQ(2, handler.num_touch_events());
  root_window()->RemovePreTargetHandler(&handler);
}

// Tests that scroll events are dispatched correctly.
TEST_F(WindowEventDispatcherTest, ScrollEventDispatch) {
  base::TimeTicks now = ui::EventTimeForNow();
  ui::test::TestEventHandler handler;
  root_window()->AddPreTargetHandler(&handler);

  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
  w1->SetBounds(gfx::Rect(20, 20, 40, 40));

  // A scroll event on the root-window itself is dispatched.
  ui::ScrollEvent scroll1(ui::ET_SCROLL,
                          gfx::Point(10, 10),
                          now,
                          0,
                          0, -10,
                          0, -10,
                          2);
  DispatchEventUsingWindowDispatcher(&scroll1);
  EXPECT_EQ(1, handler.num_scroll_events());

  // Scroll event on a window should be dispatched properly.
  ui::ScrollEvent scroll2(ui::ET_SCROLL,
                          gfx::Point(25, 30),
                          now,
                          0,
                          -10, 0,
                          -10, 0,
                          2);
  DispatchEventUsingWindowDispatcher(&scroll2);
  EXPECT_EQ(2, handler.num_scroll_events());
  root_window()->RemovePreTargetHandler(&handler);
}

namespace {

// ui::EventHandler that tracks the types of events it's seen.
class EventFilterRecorder : public ui::EventHandler {
 public:
  typedef std::vector<ui::EventType> Events;
  typedef std::vector<gfx::Point> EventLocations;
  typedef std::vector<int> EventFlags;

  EventFilterRecorder()
      : wait_until_event_(ui::ET_UNKNOWN),
        last_touch_may_cause_scrolling_(false) {
  }

  const Events& events() const { return events_; }

  const EventLocations& mouse_locations() const { return mouse_locations_; }
  gfx::Point mouse_location(int i) const { return mouse_locations_[i]; }
  const EventLocations& touch_locations() const { return touch_locations_; }
  const EventLocations& gesture_locations() const { return gesture_locations_; }
  const EventFlags& mouse_event_flags() const { return mouse_event_flags_; }

  void WaitUntilReceivedEvent(ui::EventType type) {
    wait_until_event_ = type;
    run_loop_.reset(new base::RunLoop());
    run_loop_->Run();
  }

  Events GetAndResetEvents() {
    Events events = events_;
    Reset();
    return events;
  }

  void Reset() {
    events_.clear();
    mouse_locations_.clear();
    touch_locations_.clear();
    gesture_locations_.clear();
    mouse_event_flags_.clear();
    last_touch_may_cause_scrolling_ = false;
  }

  // ui::EventHandler overrides:
  void OnEvent(ui::Event* event) override {
    ui::EventHandler::OnEvent(event);
    events_.push_back(event->type());
    if (wait_until_event_ == event->type() && run_loop_) {
      run_loop_->Quit();
      wait_until_event_ = ui::ET_UNKNOWN;
    }
  }

  void OnMouseEvent(ui::MouseEvent* event) override {
    mouse_locations_.push_back(event->location());
    mouse_event_flags_.push_back(event->flags());
  }

  void OnTouchEvent(ui::TouchEvent* event) override {
    touch_locations_.push_back(event->location());
    last_touch_may_cause_scrolling_ = event->may_cause_scrolling();
  }

  void OnGestureEvent(ui::GestureEvent* event) override {
    gesture_locations_.push_back(event->location());
  }

  bool HasReceivedEvent(ui::EventType type) {
    return base::Contains(events_, type);
  }

  bool LastTouchMayCauseScrolling() const {
    return last_touch_may_cause_scrolling_;
  }

 private:
  std::unique_ptr<base::RunLoop> run_loop_;
  ui::EventType wait_until_event_;

  Events events_;
  EventLocations mouse_locations_;
  EventLocations touch_locations_;
  EventLocations gesture_locations_;
  EventFlags mouse_event_flags_;
  bool last_touch_may_cause_scrolling_;

  DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder);
};

// Converts an EventType to a string.
std::string EventTypeToString(ui::EventType type) {
  switch (type) {
    case ui::ET_TOUCH_RELEASED:
      return "TOUCH_RELEASED";

    case ui::ET_TOUCH_CANCELLED:
      return "TOUCH_CANCELLED";

    case ui::ET_TOUCH_PRESSED:
      return "TOUCH_PRESSED";

    case ui::ET_TOUCH_MOVED:
      return "TOUCH_MOVED";

    case ui::ET_MOUSE_PRESSED:
      return "MOUSE_PRESSED";

    case ui::ET_MOUSE_DRAGGED:
      return "MOUSE_DRAGGED";

    case ui::ET_MOUSE_RELEASED:
      return "MOUSE_RELEASED";

    case ui::ET_MOUSE_MOVED:
      return "MOUSE_MOVED";

    case ui::ET_MOUSE_ENTERED:
      return "MOUSE_ENTERED";

    case ui::ET_MOUSE_EXITED:
      return "MOUSE_EXITED";

    case ui::ET_GESTURE_SCROLL_BEGIN:
      return "GESTURE_SCROLL_BEGIN";

    case ui::ET_GESTURE_SCROLL_END:
      return "GESTURE_SCROLL_END";

    case ui::ET_GESTURE_SCROLL_UPDATE:
      return "GESTURE_SCROLL_UPDATE";

    case ui::ET_GESTURE_PINCH_BEGIN:
      return "GESTURE_PINCH_BEGIN";

    case ui::ET_GESTURE_PINCH_END:
      return "GESTURE_PINCH_END";

    case ui::ET_GESTURE_PINCH_UPDATE:
      return "GESTURE_PINCH_UPDATE";

    case ui::ET_GESTURE_TAP:
      return "GESTURE_TAP";

    case ui::ET_GESTURE_TAP_DOWN:
      return "GESTURE_TAP_DOWN";

    case ui::ET_GESTURE_TAP_CANCEL:
      return "GESTURE_TAP_CANCEL";

    case ui::ET_GESTURE_SHOW_PRESS:
      return "GESTURE_SHOW_PRESS";

    case ui::ET_GESTURE_BEGIN:
      return "GESTURE_BEGIN";

    case ui::ET_GESTURE_END:
      return "GESTURE_END";

    default:
      // We should explicitly require each event type.
      NOTREACHED() << "Received unexpected event: " << type;
      break;
  }
  return "";
}

std::string EventTypesToString(const EventFilterRecorder::Events& events) {
  std::string result;
  for (size_t i = 0; i < events.size(); ++i) {
    if (i != 0)
      result += " ";
    result += EventTypeToString(events[i]);
  }
  return result;
}

}  // namespace

#if defined(OS_WIN) && defined(ARCH_CPU_X86)
#define MAYBE(x) DISABLED_##x
#else
#define MAYBE(x) x
#endif

// Verifies a repost mouse event targets the window with capture (if there is
// one).
// Flaky on 32-bit Windows bots.  http://crbug.com/388290
TEST_F(WindowEventDispatcherTest, MAYBE(RepostTargetsCaptureWindow)) {
  // Set capture on |window| generate a mouse event (that is reposted) and not
  // over |window| and verify |window| gets it (|window| gets it because it has
  // capture).
  EXPECT_FALSE(Env::GetInstance()->IsMouseButtonDown());
  EventFilterRecorder recorder;
  std::unique_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
  window->SetBounds(gfx::Rect(20, 20, 40, 30));
  window->AddPreTargetHandler(&recorder);
  window->SetCapture();
  const ui::MouseEvent press_event(
      ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
      ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
  host()->dispatcher()->RepostEvent(&press_event);
  RunAllPendingInMessageLoop();  // Necessitated by RepostEvent().
  // Mouse moves/enters may be generated. We only care about a pressed.
  EXPECT_TRUE(EventTypesToString(recorder.events()).find("MOUSE_PRESSED") !=
              std::string::npos) << EventTypesToString(recorder.events());
  window->RemovePreTargetHandler(&recorder);
}

TEST_F(WindowEventDispatcherTest, MouseMovesHeld) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));

  ui::MouseEvent mouse_move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
                                  gfx::Point(0, 0), ui::EventTimeForNow(), 0,
                                  0);
  DispatchEventUsingWindowDispatcher(&mouse_move_event);
  // Discard MOUSE_ENTER.
  recorder.Reset();

  host()->dispatcher()->HoldPointerMoves();

  // Check that we don't immediately dispatch the MOUSE_DRAGGED event.
  ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0),
                                     gfx::Point(0, 0), ui::EventTimeForNow(), 0,
                                     0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  EXPECT_TRUE(recorder.events().empty());

  // Check that we do dispatch the held MOUSE_DRAGGED event before another type
  // of event.
  ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
                                     gfx::Point(0, 0), ui::EventTimeForNow(), 0,
                                     0);
  DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
  EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
            EventTypesToString(recorder.events()));
  recorder.Reset();

  // Check that we coalesce held MOUSE_DRAGGED events. Note that here (and
  // elsewhere in this test) we re-define each event prior to dispatch so that
  // it has the correct state (phase, handled, target, etc.).
  mouse_dragged_event =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  ui::MouseEvent mouse_dragged_event2(ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10),
                                      gfx::Point(10, 10), ui::EventTimeForNow(),
                                      0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
  EXPECT_TRUE(recorder.events().empty());
  mouse_pressed_event =
      ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
  EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
            EventTypesToString(recorder.events()));
  recorder.Reset();

  // Check that on ReleasePointerMoves, held events are not dispatched
  // immediately, but posted instead.
  mouse_dragged_event =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  host()->dispatcher()->ReleasePointerMoves();
  EXPECT_TRUE(recorder.events().empty());
  RunAllPendingInMessageLoop();
  EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
  recorder.Reset();

  // However if another message comes in before the dispatch of the posted
  // event, check that the posted event is dispatched before this new event.
  host()->dispatcher()->HoldPointerMoves();
  mouse_dragged_event =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  host()->dispatcher()->ReleasePointerMoves();
  mouse_pressed_event =
      ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
  EXPECT_EQ("MOUSE_DRAGGED MOUSE_PRESSED",
            EventTypesToString(recorder.events()));
  recorder.Reset();
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  // Check that if the other message is another MOUSE_DRAGGED, we still coalesce
  // them.
  host()->dispatcher()->HoldPointerMoves();
  mouse_dragged_event =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  host()->dispatcher()->ReleasePointerMoves();
  mouse_dragged_event2 =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10),
                     gfx::Point(10, 10), ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
  EXPECT_EQ("MOUSE_DRAGGED", EventTypesToString(recorder.events()));
  recorder.Reset();
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  // Check that synthetic mouse move event has a right location when issued
  // while holding pointer moves.
  mouse_dragged_event =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(0, 0), gfx::Point(0, 0),
                     ui::EventTimeForNow(), 0, 0);
  mouse_dragged_event2 =
      ui::MouseEvent(ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10),
                     gfx::Point(10, 10), ui::EventTimeForNow(), 0, 0);
  ui::MouseEvent mouse_dragged_event3(ui::ET_MOUSE_DRAGGED, gfx::Point(28, 28),
                                      gfx::Point(28, 28), ui::EventTimeForNow(),
                                      0, 0);
  host()->dispatcher()->HoldPointerMoves();
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event);
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event2);
  window->SetBounds(gfx::Rect(15, 15, 80, 80));
  DispatchEventUsingWindowDispatcher(&mouse_dragged_event3);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());
  host()->dispatcher()->ReleasePointerMoves();
  RunAllPendingInMessageLoop();
  EXPECT_EQ("MOUSE_MOVED", EventTypesToString(recorder.events()));
  EXPECT_EQ(gfx::Point(13, 13), recorder.mouse_location(0));
  recorder.Reset();
  root_window()->RemovePreTargetHandler(&recorder);
}

TEST_F(WindowEventDispatcherTest, TouchMovesHeld) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));

  // Starting the touch and throwing out the first few events, since the system
  // is going to generate synthetic mouse events that are not relevant to the
  // test.
  ui::TouchEvent touch_pressed_event(
      ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&touch_pressed_event);
  recorder.WaitUntilReceivedEvent(ui::ET_GESTURE_SHOW_PRESS);
  recorder.Reset();

  host()->dispatcher()->HoldPointerMoves();

  // Check that we don't immediately dispatch the TOUCH_MOVED event.
  ui::TouchEvent touch_moved_event(
      ui::ET_TOUCH_MOVED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  ui::TouchEvent touch_moved_event2(
      ui::ET_TOUCH_MOVED, gfx::Point(11, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  ui::TouchEvent touch_moved_event3(
      ui::ET_TOUCH_MOVED, gfx::Point(12, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));

  DispatchEventUsingWindowDispatcher(&touch_moved_event);
  EXPECT_TRUE(recorder.events().empty());

  // Check that on ReleasePointerMoves, held events are not dispatched
  // immediately, but posted instead.
  DispatchEventUsingWindowDispatcher(&touch_moved_event2);
  host()->dispatcher()->ReleasePointerMoves();
  EXPECT_TRUE(recorder.events().empty());

  RunAllPendingInMessageLoop();
  EXPECT_EQ("TOUCH_MOVED", EventTypesToString(recorder.events()));
  recorder.Reset();

  // If another touch event occurs then the held touch should be dispatched
  // immediately before it.
  ui::TouchEvent touch_released_event(
      ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  recorder.Reset();
  host()->dispatcher()->HoldPointerMoves();
  DispatchEventUsingWindowDispatcher(&touch_moved_event3);
  DispatchEventUsingWindowDispatcher(&touch_released_event);
  EXPECT_EQ("TOUCH_MOVED TOUCH_RELEASED GESTURE_TAP GESTURE_END",
            EventTypesToString(recorder.events()));
  recorder.Reset();
  host()->dispatcher()->ReleasePointerMoves();
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());
  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that mouse move event has a right location
// when there isn't the target window
TEST_F(WindowEventDispatcherTest, MouseEventWithoutTargetWindow) {
  EventFilterRecorder recorder_first;
  EventFilterRecorder recorder_second;

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window_first(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(20, 10, 10, 20), root_window()));
  window_first->Show();
  window_first->AddPreTargetHandler(&recorder_first);

  std::unique_ptr<aura::Window> window_second(CreateTestWindowWithDelegate(
      &delegate, 2, gfx::Rect(20, 30, 10, 20), root_window()));
  window_second->Show();
  window_second->AddPreTargetHandler(&recorder_second);

  const gfx::Point event_location(22, 33);
  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                       ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse);

  EXPECT_TRUE(recorder_first.events().empty());
  EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED",
            EventTypesToString(recorder_second.events()));
  ASSERT_EQ(2u, recorder_second.mouse_locations().size());
  EXPECT_EQ(gfx::Point(2, 3).ToString(),
            recorder_second.mouse_locations()[0].ToString());

  window_first->RemovePreTargetHandler(&recorder_first);
  window_second->RemovePreTargetHandler(&recorder_second);
}

// Tests that a mouse exit is dispatched to the last mouse location when
// the window is hiddden.
TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenHidingWindow) {
  EventFilterRecorder recorder;

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(10, 10, 50, 50), root_window()));
  window->Show();
  window->AddPreTargetHandler(&recorder);

  // Dispatch a mouse move event into the window.
  const gfx::Point event_location(22, 33);
  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                       ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Hide the window and verify a mouse exit event's location.
  window->Hide();
  EXPECT_FALSE(recorder.events().empty());
  EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events()));
  ASSERT_EQ(1u, recorder.mouse_locations().size());
  EXPECT_EQ(gfx::Point(12, 23).ToString(),
            recorder.mouse_locations()[0].ToString());
  window->RemovePreTargetHandler(&recorder);
}

// Tests that a mouse-exit event is not synthesized during shutdown.
TEST_F(WindowEventDispatcherTest, NoMouseExitInShutdown) {
  EventFilterRecorder recorder;
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(10, 10, 50, 50), root_window()));
  window->Show();
  window->AddPreTargetHandler(&recorder);

  // Simulate mouse move into the window.
  const gfx::Point event_location = window->bounds().CenterPoint();
  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                       ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Simulate shutdown.
  host()->dispatcher()->Shutdown();

  // Hiding the window does not generate a mouse-exit event.
  window->Hide();
  EXPECT_TRUE(recorder.events().empty());
  window->RemovePreTargetHandler(&recorder);
}

// Verifies that a direct call to ProcessedTouchEvent() does not cause a crash.
TEST_F(WindowEventDispatcherTest, CallToProcessedTouchEvent) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));

  host()->dispatcher()->ProcessedTouchEvent(
      0, window.get(), ui::ER_UNHANDLED,
      false /* is_source_touch_event_set_non_blocking */);
}

// This event handler requests the dispatcher to start holding pointer-move
// events when it receives the first scroll-update gesture.
class HoldPointerOnScrollHandler : public ui::test::TestEventHandler {
 public:
  HoldPointerOnScrollHandler(WindowEventDispatcher* dispatcher,
                             EventFilterRecorder* filter)
      : dispatcher_(dispatcher),
        filter_(filter),
        holding_moves_(false) {}
  ~HoldPointerOnScrollHandler() override {}

 private:
  // ui::test::TestEventHandler:
  void OnGestureEvent(ui::GestureEvent* gesture) override {
    if (!holding_moves_ && gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
      holding_moves_ = true;
      dispatcher_->HoldPointerMoves();
      filter_->Reset();
    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
      dispatcher_->ReleasePointerMoves();
      holding_moves_ = false;
    }
  }

  WindowEventDispatcher* dispatcher_;
  EventFilterRecorder* filter_;
  bool holding_moves_;

  DISALLOW_COPY_AND_ASSIGN(HoldPointerOnScrollHandler);
};

// Tests that touch-move events don't contribute to an in-progress scroll
// gesture if touch-move events are being held by the dispatcher.
TEST_F(WindowEventDispatcherTest, TouchMovesHeldOnScroll) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);
  test::TestWindowDelegate delegate;
  HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
  window->AddPreTargetHandler(&handler);

  ui::test::EventGenerator generator(root_window());
  generator.GestureScrollSequence(
      gfx::Point(60, 60), gfx::Point(10, 60),
      base::TimeDelta::FromMilliseconds(100), 25);

  // |handler| will have reset |filter| and started holding the touch-move
  // events when scrolling started. At the end of the scroll (i.e. upon
  // touch-release), the held touch-move event will have been dispatched first,
  // along with the subsequent events (i.e. touch-release, scroll-end, and
  // gesture-end).
  const EventFilterRecorder::Events& events = recorder.events();
  EXPECT_EQ(
      "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
      "GESTURE_SCROLL_END GESTURE_END",
      EventTypesToString(events));
  ASSERT_EQ(2u, recorder.touch_locations().size());
  EXPECT_EQ(gfx::Point(-40, 10).ToString(),
            recorder.touch_locations()[0].ToString());
  EXPECT_EQ(gfx::Point(-40, 10).ToString(),
            recorder.touch_locations()[1].ToString());
  window->RemovePreTargetHandler(&handler);
  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that a 'held' touch-event does contribute to gesture event when it is
// dispatched.
TEST_F(WindowEventDispatcherTest, HeldTouchMoveContributesToGesture) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  const gfx::Point location(20, 20);
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_PRESSED));
  recorder.Reset();

  host()->dispatcher()->HoldPointerMoves();

  ui::TouchEvent move(
      ui::ET_TOUCH_MOVED, location + gfx::Vector2d(100, 100),
      ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&move);
  EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
  EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
  recorder.Reset();

  host()->dispatcher()->ReleasePointerMoves();
  EXPECT_FALSE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_UPDATE));

  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that synthetic mouse events are ignored when mouse
// events are disabled.
TEST_F(WindowEventDispatcherTest, DispatchSyntheticMouseEvents) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
  window->Show();
  window->SetCapture();

  test::TestCursorClient cursor_client(root_window());

  // Dispatch a non-synthetic mouse event when mouse events are enabled.
  ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse1);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Dispatch a synthetic mouse event when mouse events are enabled.
  ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeForNow(),
                        ui::EF_IS_SYNTHESIZED, 0);
  DispatchEventUsingWindowDispatcher(&mouse2);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Dispatch a synthetic mouse event when mouse events are disabled.
  cursor_client.DisableMouseEvents();
  DispatchEventUsingWindowDispatcher(&mouse2);
  EXPECT_TRUE(recorder.events().empty());
  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that a mouse-move event is not synthesized when a mouse-button is down.
TEST_F(WindowEventDispatcherTest, DoNotSynthesizeWhileButtonDown) {
  EventFilterRecorder recorder;
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
  window->Show();

  window->AddPreTargetHandler(&recorder);
  // Dispatch a non-synthetic mouse event when mouse events are enabled.
  ui::MouseEvent mouse1(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeForNow(),
                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse1);
  ASSERT_EQ(1u, recorder.events().size());
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder.events()[0]);
  window->RemovePreTargetHandler(&recorder);
  recorder.Reset();

  // Move |window| away from underneath the cursor.
  root_window()->AddPreTargetHandler(&recorder);
  window->SetBounds(gfx::Rect(30, 30, 100, 100));
  EXPECT_TRUE(recorder.events().empty());
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());
  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that a mouse-press event is not dispatched during shutdown.
TEST_F(WindowEventDispatcherTest, DoNotDispatchInShutdown) {
  EventFilterRecorder recorder;
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
  window->Show();
  window->AddPreTargetHandler(&recorder);

  // Simulate shutdown.
  host()->dispatcher()->Shutdown();

  // Attempt to dispatch a mouse press.
  const gfx::Point center = window->bounds().CenterPoint();
  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, center, center,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&press);

  // Event was not dispatched.
  EXPECT_TRUE(recorder.events().empty());
  window->RemovePreTargetHandler(&recorder);
}

#if defined(OS_WIN) && defined(ARCH_CPU_X86)
#define MAYBE(x) DISABLED_##x
#else
#define MAYBE(x) x
#endif

// Tests synthetic mouse events generated when window bounds changes such that
// the cursor previously outside the window becomes inside, or vice versa.
// Do not synthesize events if the window ignores events or is invisible.
// Flaky on 32-bit Windows bots.  http://crbug.com/388272
TEST_F(WindowEventDispatcherTest,
       MAYBE(SynthesizeMouseEventsOnWindowBoundsChanged)) {
  test::TestCursorClient cursor_client(root_window());
  cursor_client.ShowCursor();

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
  window->Show();
  window->SetCapture();

  EventFilterRecorder recorder;
  window->AddPreTargetHandler(&recorder);

  // Dispatch a non-synthetic mouse event to place cursor inside window bounds.
  ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                       gfx::Point(10, 10), ui::EventTimeForNow(), 0, 0);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Update the window bounds so that cursor is now outside the window.
  // This should trigger a synthetic MOVED event.
  gfx::Rect bounds1(20, 20, 100, 100);
  window->SetBounds(bounds1);
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(recorder.events().empty());
  ASSERT_FALSE(recorder.mouse_event_flags().empty());
  EXPECT_EQ(ui::ET_MOUSE_MOVED, recorder.events().back());
  EXPECT_EQ(ui::EF_IS_SYNTHESIZED, recorder.mouse_event_flags().back());
  recorder.Reset();

  // Set window to ignore events.
  window->SetEventTargetingPolicy(EventTargetingPolicy::kNone);

  // Update the window bounds so that cursor is back inside the window.
  // This should not trigger a synthetic event.
  gfx::Rect bounds2(5, 5, 100, 100);
  window->SetBounds(bounds2);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());
  recorder.Reset();

  // Set window to accept events but invisible.
  window->SetEventTargetingPolicy(EventTargetingPolicy::kTargetAndDescendants);
  window->Hide();
  recorder.Reset();

  // Update the window bounds so that cursor is outside the window.
  // This should not trigger a synthetic event.
  window->SetBounds(bounds1);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  // Hide the cursor. None of the following scenario should trigger
  // a synthetic event.
  cursor_client.HideCursor();

  window->Show();
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  window->SetBounds(bounds2);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  window->SetBounds(bounds1);
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  cursor_client.ShowCursor();
  window->SetBounds(bounds2);
  RunAllPendingInMessageLoop();
  ASSERT_FALSE(recorder.events().empty());
  ASSERT_FALSE(recorder.mouse_event_flags().empty());
  EXPECT_EQ(ui::ET_MOUSE_MOVED, recorder.events().back());
  EXPECT_EQ(ui::EF_IS_SYNTHESIZED, recorder.mouse_event_flags().back());
  recorder.Reset();
  window->RemovePreTargetHandler(&recorder);
}

// Tests that a mouse exit is dispatched to the last known cursor location
// when the cursor becomes invisible.
TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenCursorHidden) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  gfx::Point window_origin(7, 18);
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
      root_window()));
  window->Show();

  // Dispatch a mouse move event into the window.
  gfx::Point mouse_location(gfx::Point(15, 25));
  ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location, mouse_location,
                        ui::EventTimeForNow(), 0, 0);
  EXPECT_TRUE(recorder.events().empty());
  DispatchEventUsingWindowDispatcher(&mouse1);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  // Hide the cursor and verify a mouse exit was dispatched.
  host()->OnCursorVisibilityChanged(false);
  EXPECT_FALSE(recorder.events().empty());
  EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events()));

  // Verify the mouse exit was dispatched at the correct location
  // (in the correct coordinate space).
  int translated_x = mouse_location.x() - window_origin.x();
  int translated_y = mouse_location.y() - window_origin.y();
  gfx::Point translated_point(translated_x, translated_y);
  EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());

  // Verify the mouse exit with ui::EF_CURSOR_HIDE flags.
  EXPECT_TRUE(recorder.mouse_event_flags()[0] & ui::EF_CURSOR_HIDE);
  root_window()->RemovePreTargetHandler(&recorder);
}

// Tests that a synthetic mouse exit is dispatched to the last known cursor
// location after mouse events are disabled on the cursor client.
TEST_F(WindowEventDispatcherTest,
       DispatchSyntheticMouseExitAfterMouseEventsDisabled) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  gfx::Point window_origin(7, 18);
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)),
      root_window()));
  window->Show();

  // Dispatch a mouse move event into the window.
  gfx::Point mouse_location(gfx::Point(15, 25));
  ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location, mouse_location,
                        ui::EventTimeForNow(), 0, 0);
  EXPECT_TRUE(recorder.events().empty());
  DispatchEventUsingWindowDispatcher(&mouse1);
  EXPECT_FALSE(recorder.events().empty());
  recorder.Reset();

  test::TestCursorClient cursor_client(root_window());
  cursor_client.DisableMouseEvents();

  gfx::Point mouse_exit_location(gfx::Point(150, 150));
  ui::MouseEvent mouse2(ui::ET_MOUSE_EXITED, gfx::Point(150, 150),
                        gfx::Point(150, 150), ui::EventTimeForNow(),
                        ui::EF_IS_SYNTHESIZED, 0);
  DispatchEventUsingWindowDispatcher(&mouse2);

  EXPECT_FALSE(recorder.events().empty());
  // We get the mouse exited event twice in our filter. Once during the
  // predispatch phase and during the actual dispatch.
  EXPECT_EQ("MOUSE_EXITED MOUSE_EXITED", EventTypesToString(recorder.events()));

  // Verify the mouse exit was dispatched at the correct location
  // (in the correct coordinate space).
  int translated_x = mouse_exit_location.x() - window_origin.x();
  int translated_y = mouse_exit_location.y() - window_origin.y();
  gfx::Point translated_point(translated_x, translated_y);
  EXPECT_EQ(recorder.mouse_location(0).ToString(), translated_point.ToString());
  root_window()->RemovePreTargetHandler(&recorder);
}

class DeletingEventFilter : public ui::EventHandler {
 public:
  DeletingEventFilter()
      : delete_during_pre_handle_(false) {}
  ~DeletingEventFilter() override {}

  void Reset(bool delete_during_pre_handle) {
    delete_during_pre_handle_ = delete_during_pre_handle;
  }

 private:
  // Overridden from ui::EventHandler:
  void OnKeyEvent(ui::KeyEvent* event) override {
    if (delete_during_pre_handle_)
      delete event->target();
  }

  void OnMouseEvent(ui::MouseEvent* event) override {
    if (delete_during_pre_handle_)
      delete event->target();
  }

  bool delete_during_pre_handle_;

  DISALLOW_COPY_AND_ASSIGN(DeletingEventFilter);
};

class DeletingWindowDelegate : public test::TestWindowDelegate {
 public:
  DeletingWindowDelegate()
      : window_(NULL),
        delete_during_handle_(false),
        got_event_(false) {}
  ~DeletingWindowDelegate() override {}

  void Reset(Window* window, bool delete_during_handle) {
    window_ = window;
    delete_during_handle_ = delete_during_handle;
    got_event_ = false;
  }
  bool got_event() const { return got_event_; }

 private:
  // Overridden from WindowDelegate:
  void OnKeyEvent(ui::KeyEvent* event) override {
    if (delete_during_handle_)
      delete window_;
    got_event_ = true;
  }

  void OnMouseEvent(ui::MouseEvent* event) override {
    if (delete_during_handle_)
      delete window_;
    got_event_ = true;
  }

  Window* window_;
  bool delete_during_handle_;
  bool got_event_;

  DISALLOW_COPY_AND_ASSIGN(DeletingWindowDelegate);
};

TEST_F(WindowEventDispatcherTest, DeleteWindowDuringDispatch) {
  // Verifies that we can delete a window during each phase of event handling.
  // Deleting the window should not cause a crash, only prevent further
  // processing from occurring.
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
  DeletingWindowDelegate d11;
  Window* w11 = CreateNormalWindow(11, w1.get(), &d11);
  WindowTracker tracker;
  DeletingEventFilter w1_filter;
  w1->AddPreTargetHandler(&w1_filter);
  client::GetFocusClient(w1.get())->FocusWindow(w11);

  ui::test::EventGenerator generator(root_window(), w11);

  // First up, no one deletes anything.
  tracker.Add(w11);
  d11.Reset(w11, false);

  generator.PressLeftButton();
  EXPECT_TRUE(tracker.Contains(w11));
  EXPECT_TRUE(d11.got_event());
  generator.ReleaseLeftButton();

  // Delegate deletes w11. This will prevent the post-handle step from applying.
  w1_filter.Reset(false);
  d11.Reset(w11, true);
  generator.PressKey(ui::VKEY_A, 0);
  EXPECT_FALSE(tracker.Contains(w11));
  EXPECT_TRUE(d11.got_event());

  // Pre-handle step deletes w11. This will prevent the delegate and the post-
  // handle steps from applying.
  w11 = CreateNormalWindow(11, w1.get(), &d11);
  w1_filter.Reset(true);
  d11.Reset(w11, false);
  generator.PressLeftButton();
  EXPECT_FALSE(tracker.Contains(w11));
  EXPECT_FALSE(d11.got_event());

  w1->RemovePreTargetHandler(&w1_filter);
}

namespace {

// A window delegate that detaches the parent of the target's parent window when
// it receives a tap event.
class DetachesParentOnTapDelegate : public test::TestWindowDelegate {
 public:
  DetachesParentOnTapDelegate() {}
  ~DetachesParentOnTapDelegate() override {}

 private:
  void OnGestureEvent(ui::GestureEvent* event) override {
    if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
      event->SetHandled();
      return;
    }

    if (event->type() == ui::ET_GESTURE_TAP) {
      Window* parent = static_cast<Window*>(event->target())->parent();
      parent->parent()->RemoveChild(parent);
      event->SetHandled();
    }
  }

  DISALLOW_COPY_AND_ASSIGN(DetachesParentOnTapDelegate);
};

}  // namespace

// Tests that the gesture recognizer is reset for all child windows when a
// window hides. No expectations, just checks that the test does not crash.
TEST_F(WindowEventDispatcherTest,
       GestureRecognizerResetsTargetWhenParentHides) {
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
  DetachesParentOnTapDelegate delegate;
  std::unique_ptr<Window> parent(CreateNormalWindow(22, w1.get(), NULL));
  Window* child = CreateNormalWindow(11, parent.get(), &delegate);
  ui::test::EventGenerator generator(root_window(), child);
  generator.GestureTapAt(gfx::Point(40, 40));
}

namespace {

// A window delegate that processes nested gestures on tap.
class NestedGestureDelegate : public test::TestWindowDelegate {
 public:
  NestedGestureDelegate(ui::test::EventGenerator* generator,
                        const gfx::Point tap_location)
      : generator_(generator),
        tap_location_(tap_location),
        gesture_end_count_(0) {}
  ~NestedGestureDelegate() override {}

  int gesture_end_count() const { return gesture_end_count_; }

 private:
  void OnGestureEvent(ui::GestureEvent* event) override {
    switch (event->type()) {
      case ui::ET_GESTURE_TAP_DOWN:
        event->SetHandled();
        break;
      case ui::ET_GESTURE_TAP:
        if (generator_)
          generator_->GestureTapAt(tap_location_);
        event->SetHandled();
        break;
      case ui::ET_GESTURE_END:
        ++gesture_end_count_;
        break;
      default:
        break;
    }
  }

  ui::test::EventGenerator* generator_;
  const gfx::Point tap_location_;
  int gesture_end_count_;
  DISALLOW_COPY_AND_ASSIGN(NestedGestureDelegate);
};

}  // namespace

// Tests that gesture end is delivered after nested gesture processing.
TEST_F(WindowEventDispatcherTest, GestureEndDeliveredAfterNestedGestures) {
  NestedGestureDelegate d1(NULL, gfx::Point());
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), &d1));
  w1->SetBounds(gfx::Rect(0, 0, 100, 100));

  ui::test::EventGenerator nested_generator(root_window(), w1.get());
  NestedGestureDelegate d2(&nested_generator, w1->bounds().CenterPoint());
  std::unique_ptr<Window> w2(CreateNormalWindow(1, root_window(), &d2));
  w2->SetBounds(gfx::Rect(100, 0, 100, 100));

  // Tap on w2 which triggers nested gestures for w1.
  ui::test::EventGenerator generator(root_window(), w2.get());
  generator.GestureTapAt(w2->bounds().CenterPoint());

  // Both windows should get their gesture end events.
  EXPECT_EQ(1, d1.gesture_end_count());
  EXPECT_EQ(1, d2.gesture_end_count());
}

// Tests whether we can repost the Tap down gesture event.
TEST_F(WindowEventDispatcherTest, RepostTapdownGestureTest) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));

  ui::GestureEventDetails details(ui::ET_GESTURE_TAP_DOWN);
  gfx::Point point(10, 10);
  ui::GestureEvent event(point.x(),
                         point.y(),
                         0,
                         ui::EventTimeForNow(),
                         details);
  host()->dispatcher()->RepostEvent(&event);
  RunAllPendingInMessageLoop();
  // TODO(rbyers): Currently disabled - crbug.com/170987
  EXPECT_FALSE(EventTypesToString(recorder.events()).find("GESTURE_TAP_DOWN") !=
              std::string::npos);
  recorder.Reset();
  root_window()->RemovePreTargetHandler(&recorder);
}

// This class inherits from the EventFilterRecorder class which provides a
// facility to record events. This class additionally provides a facility to
// repost the ET_GESTURE_TAP_DOWN gesture to the target window and records
// events after that.
class RepostGestureEventRecorder : public EventFilterRecorder {
 public:
  RepostGestureEventRecorder(aura::Window* repost_source,
                             aura::Window* repost_target)
      : repost_source_(repost_source),
        repost_target_(repost_target),
        reposted_(false),
        done_cleanup_(false) {}

  ~RepostGestureEventRecorder() override {}

  void OnTouchEvent(ui::TouchEvent* event) override {
    if (reposted_ && event->type() == ui::ET_TOUCH_PRESSED) {
      done_cleanup_ = true;
      Reset();
    }
    EventFilterRecorder::OnTouchEvent(event);
  }

  void OnGestureEvent(ui::GestureEvent* event) override {
    EXPECT_EQ(done_cleanup_ ? repost_target_ : repost_source_, event->target());
    if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
      if (!reposted_) {
        EXPECT_NE(repost_target_, event->target());
        reposted_ = true;
        repost_target_->GetHost()->dispatcher()->RepostEvent(event);
        // Ensure that the reposted gesture event above goes to the
        // repost_target_;
        repost_source_->GetRootWindow()->RemoveChild(repost_source_);
        return;
      }
    }
    EventFilterRecorder::OnGestureEvent(event);
  }

  // Ignore mouse events as they don't fire at all times. This causes
  // the GestureRepostEventOrder test to fail randomly.
  void OnMouseEvent(ui::MouseEvent* event) override {}

 private:
  aura::Window* repost_source_;
  aura::Window* repost_target_;
  // set to true if we reposted the ET_GESTURE_TAP_DOWN event.
  bool reposted_;
  // set true if we're done cleaning up after hiding repost_source_;
  bool done_cleanup_;
  DISALLOW_COPY_AND_ASSIGN(RepostGestureEventRecorder);
};

// Tests whether events which are generated after the reposted gesture event
// are received after that. In this case the scroll sequence events should
// be received after the reposted gesture event.
TEST_F(WindowEventDispatcherTest, GestureRepostEventOrder) {
  // Expected events at the end for the repost_target window defined below.
  const char kExpectedTargetEvents[] =
    // TODO)(rbyers): Gesture event reposting is disabled - crbug.com/279039.
    // "GESTURE_BEGIN GESTURE_TAP_DOWN "
    "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
    "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE TOUCH_MOVED "
    "GESTURE_SCROLL_UPDATE TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
    "GESTURE_SCROLL_END GESTURE_END";
  // We create two windows.
  // The first window (repost_source) is the one to which the initial tap
  // gesture is sent. It reposts this event to the second window
  // (repost_target).
  // We then generate the scroll sequence for repost_target and look for two
  // ET_GESTURE_TAP_DOWN events in the event list at the end.
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> repost_target(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));

  std::unique_ptr<aura::Window> repost_source(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 50, 50), root_window()));

  RepostGestureEventRecorder repost_event_recorder(repost_source.get(),
                                                   repost_target.get());
  root_window()->AddPreTargetHandler(&repost_event_recorder);

  // Generate a tap down gesture for the repost_source. This will be reposted
  // to repost_target.
  ui::test::EventGenerator repost_generator(root_window(), repost_source.get());
  repost_generator.GestureTapAt(gfx::Point(40, 40));
  RunAllPendingInMessageLoop();

  ui::test::EventGenerator scroll_generator(root_window(), repost_target.get());
  scroll_generator.GestureScrollSequence(
      gfx::Point(80, 80),
      gfx::Point(100, 100),
      base::TimeDelta::FromMilliseconds(100),
      3);
  RunAllPendingInMessageLoop();

  int tap_down_count = 0;
  for (size_t i = 0; i < repost_event_recorder.events().size(); ++i) {
    if (repost_event_recorder.events()[i] == ui::ET_GESTURE_TAP_DOWN)
      ++tap_down_count;
  }

  // We expect two tap down events. One from the repost and the other one from
  // the scroll sequence posted above.
  // TODO(rbyers): Currently disabled - crbug.com/170987
  EXPECT_EQ(1, tap_down_count);

  EXPECT_EQ(kExpectedTargetEvents,
            EventTypesToString(repost_event_recorder.events()));
  root_window()->RemovePreTargetHandler(&repost_event_recorder);
}

// An event filter that deletes the specified object when sees a mouse-exited
// event.
template <class T>
class OnMouseExitDeletingEventFilter : public EventFilterRecorder {
 public:
  explicit OnMouseExitDeletingEventFilter(T* object_to_delete)
      : object_to_delete_(object_to_delete) {}
  OnMouseExitDeletingEventFilter() : object_to_delete_(nullptr) {}
  ~OnMouseExitDeletingEventFilter() override {}

  void set_object_to_delete(T* object_to_delete) {
    object_to_delete_ = object_to_delete;
  }

  void set_delete_closure(base::OnceClosure delete_closure) {
    delete_closure_ = std::move(delete_closure);
  }

 private:
  // Overridden from ui::EventFilterRecorder.
  void OnMouseEvent(ui::MouseEvent* event) override {
    EventFilterRecorder::OnMouseEvent(event);
    if (object_to_delete_ && event->type() == ui::ET_MOUSE_EXITED) {
      if (delete_closure_)
        std::move(delete_closure_).Run();
      delete object_to_delete_;
      object_to_delete_ = nullptr;
    }
  }

  // Closure that is run prior to |object_to_delete_| being deleted.
  base::OnceClosure delete_closure_;
  T* object_to_delete_;

  DISALLOW_COPY_AND_ASSIGN(OnMouseExitDeletingEventFilter);
};

// Tests that RootWindow drops mouse-moved event that is supposed to be sent to
// a child, but the child is destroyed because of the synthesized mouse-exit
// event generated on the previous mouse_moved_handler_.
TEST_F(WindowEventDispatcherTest, DeleteWindowDuringMouseMovedDispatch) {
  // Create window 1 and set its event filter. Window 1 will take ownership of
  // the event filter.
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), NULL));
  OnMouseExitDeletingEventFilter<Window> w1_filter;
  w1->AddPreTargetHandler(&w1_filter);
  w1->SetBounds(gfx::Rect(20, 20, 60, 60));
  EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());

  ui::test::EventGenerator generator(root_window(), w1.get());

  // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the
  // root window.
  generator.MoveMouseTo(51, 51);
  EXPECT_EQ(w1.get(), host()->dispatcher()->mouse_moved_handler());

  // Create window 2 under the mouse cursor and stack it above window 1.
  Window* w2 = CreateNormalWindow(2, root_window(), NULL);
  w2->SetBounds(gfx::Rect(30, 30, 40, 40));
  root_window()->StackChildAbove(w2, w1.get());

  // Set window 2 as the window that is to be deleted when a mouse-exited event
  // happens on window 1.
  w1_filter.set_object_to_delete(w2);
  // Move mouse over window 2. This should generate a mouse-exited event for
  // window 1 resulting in deletion of window 2. The original mouse-moved event
  // that was targeted to window 2 should be dropped since window 2 is
  // destroyed. This test passes if no crash happens.
  generator.MoveMouseTo(52, 52);
  EXPECT_EQ(NULL, host()->dispatcher()->mouse_moved_handler());

  // Check events received by window 1.
  EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED MOUSE_EXITED",
            EventTypesToString(w1_filter.events()));
  w1->RemovePreTargetHandler(&w1_filter);
}

// Tests the case where the event dispatcher is deleted during the pre-dispatch
// phase of dispatching and event.
TEST_F(WindowEventDispatcherTest, DeleteDispatcherDuringPreDispatch) {
  // Create a host for the window hierarchy. This host will be destroyed later
  // on.
  WindowTreeHost* host =
      WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 100, 100)})
          .release();
  host->InitHost();
  host->window()->Show();

  // Create two windows.
  Window* w1 = CreateNormalWindow(1, host->window(), nullptr);
  w1->SetBounds(gfx::Rect(20, 20, 60, 60));
  Window* w2 = CreateNormalWindow(2, host->window(), nullptr);
  w2->SetBounds(gfx::Rect(80, 20, 120, 60));
  EXPECT_EQ(nullptr, host->dispatcher()->mouse_moved_handler());

  ui::test::EventGenerator generator(host->window(), w1);

  // Move mouse over window 1 to set it as the |mouse_moved_handler_| for the
  // root window.
  generator.MoveMouseTo(40, 40);
  EXPECT_EQ(w1, host->dispatcher()->mouse_moved_handler());

  // Set appropriate event filters for the two windows with the window tree host
  // as the object that is to be deleted when a mouse-exited event happens on
  // window 1. The windows will take ownership of the event filters.
  OnMouseExitDeletingEventFilter<WindowTreeHost> w1_filter(host);
  w1->AddPreTargetHandler(&w1_filter);
  EventFilterRecorder w2_filter;
  w2->AddPreTargetHandler(&w2_filter);

  w1_filter.set_delete_closure(
      base::BindLambdaForTesting([&w1_filter, &w2_filter, &w1, &w2]() {
        w1->RemovePreTargetHandler(&w1_filter);
        w2->RemovePreTargetHandler(&w2_filter);
      }));

  // Move mouse over window 2. This should generate a mouse-exited event for
  // window 1 resulting in deletion of window tree host and its event
  // dispatcher. The event dispatching should abort since the dispatcher is
  // destroyed. This test passes if no crash happens.
  // Here we can't use EventGenerator since it expects that the dispatcher is
  // not destroyed at the end of the dispatch.
  ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, gfx::Point(20, 20),
                            gfx::Point(20, 20), base::TimeTicks(), 0, 0);
  ui::EventDispatchDetails details =
      host->dispatcher()->DispatchEvent(w2, &mouse_move);
  EXPECT_TRUE(details.dispatcher_destroyed);

  // Check events received by the two windows.
  EXPECT_EQ("MOUSE_EXITED", EventTypesToString(w1_filter.events()));
  EXPECT_EQ(std::string(), EventTypesToString(w2_filter.events()));
}

namespace {

// Used to track if OnWindowDestroying() is invoked and if there is a valid
// RootWindow at such time.
class ValidRootDuringDestructionWindowObserver : public aura::WindowObserver {
 public:
  ValidRootDuringDestructionWindowObserver(bool* got_destroying,
                                           bool* has_valid_root)
      : got_destroying_(got_destroying),
        has_valid_root_(has_valid_root) {
  }

  // WindowObserver:
  void OnWindowDestroying(aura::Window* window) override {
    *got_destroying_ = true;
    *has_valid_root_ = (window->GetRootWindow() != NULL);
  }

 private:
  bool* got_destroying_;
  bool* has_valid_root_;

  DISALLOW_COPY_AND_ASSIGN(ValidRootDuringDestructionWindowObserver);
};

}  // namespace

// Verifies GetRootWindow() from ~Window returns a valid root.
TEST_F(WindowEventDispatcherTest, ValidRootDuringDestruction) {
  bool got_destroying = false;
  bool has_valid_root = false;
  ValidRootDuringDestructionWindowObserver observer(&got_destroying,
                                                    &has_valid_root);
  {
    std::unique_ptr<WindowTreeHost> host = WindowTreeHost::Create(
        ui::PlatformWindowInitProperties{gfx::Rect(0, 0, 100, 100)});
    host->InitHost();
    host->window()->Show();
    // Owned by WindowEventDispatcher.
    Window* w1 = CreateNormalWindow(1, host->window(), NULL);
    w1->AddObserver(&observer);
  }
  EXPECT_TRUE(got_destroying);
  EXPECT_TRUE(has_valid_root);
}

namespace {

// See description above DontResetHeldEvent for details.
class DontResetHeldEventWindowDelegate : public test::TestWindowDelegate {
 public:
  explicit DontResetHeldEventWindowDelegate(aura::Window* root)
      : root_(root),
        mouse_event_count_(0) {}
  ~DontResetHeldEventWindowDelegate() override {}

  int mouse_event_count() const { return mouse_event_count_; }

  // TestWindowDelegate:
  void OnMouseEvent(ui::MouseEvent* event) override {
    if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 &&
        mouse_event_count_++ == 0) {
      ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                                 gfx::Point(10, 10), ui::EventTimeForNow(),
                                 ui::EF_SHIFT_DOWN, 0);
      root_->GetHost()->dispatcher()->RepostEvent(&mouse_event);
    }
  }

 private:
  Window* root_;
  int mouse_event_count_;

  DISALLOW_COPY_AND_ASSIGN(DontResetHeldEventWindowDelegate);
};

}  // namespace

// Verifies RootWindow doesn't reset |RootWindow::held_repostable_event_| after
// dispatching. This is done by using DontResetHeldEventWindowDelegate, which
// tracks the number of events with ui::EF_SHIFT_DOWN set (all reposted events
// have EF_SHIFT_DOWN). When the first event is seen RepostEvent() is used to
// schedule another reposted event.
TEST_F(WindowEventDispatcherTest, DontResetHeldEvent) {
  DontResetHeldEventWindowDelegate delegate(root_window());
  std::unique_ptr<Window> w1(CreateNormalWindow(1, root_window(), &delegate));
  w1->SetBounds(gfx::Rect(0, 0, 40, 40));
  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                         gfx::Point(10, 10), ui::EventTimeForNow(),
                         ui::EF_SHIFT_DOWN, 0);
  root_window()->GetHost()->dispatcher()->RepostEvent(&pressed);
  ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                          gfx::Point(10, 10), ui::EventTimeForNow(), 0, 0);
  // Dispatch an event to flush event scheduled by way of RepostEvent().
  DispatchEventUsingWindowDispatcher(&pressed2);
  // Delegate should have seen reposted event (identified by way of
  // EF_SHIFT_DOWN). Dispatch another event to flush the second
  // RepostedEvent().
  EXPECT_EQ(1, delegate.mouse_event_count());
  DispatchEventUsingWindowDispatcher(&pressed2);
  EXPECT_EQ(2, delegate.mouse_event_count());
}

namespace {

// See description above DeleteHostFromHeldMouseEvent for details.
class DeleteHostFromHeldMouseEventDelegate
    : public test::TestWindowDelegate {
 public:
  explicit DeleteHostFromHeldMouseEventDelegate(WindowTreeHost* host)
      : host_(host),
        got_mouse_event_(false),
        got_destroy_(false) {
  }
  ~DeleteHostFromHeldMouseEventDelegate() override {}

  bool got_mouse_event() const { return got_mouse_event_; }
  bool got_destroy() const { return got_destroy_; }

  // TestWindowDelegate:
  void OnMouseEvent(ui::MouseEvent* event) override {
    if ((event->flags() & ui::EF_SHIFT_DOWN) != 0) {
      got_mouse_event_ = true;
      delete host_;
    }
  }
  void OnWindowDestroyed(Window* window) override { got_destroy_ = true; }

 private:
  WindowTreeHost* host_;
  bool got_mouse_event_;
  bool got_destroy_;

  DISALLOW_COPY_AND_ASSIGN(DeleteHostFromHeldMouseEventDelegate);
};

}  // namespace

// Verifies if a WindowTreeHost is deleted from dispatching a held mouse event
// we don't crash.
TEST_F(WindowEventDispatcherTest, DeleteHostFromHeldMouseEvent) {
  // Should be deleted by |delegate|.
  WindowTreeHost* h2 = WindowTreeHost::Create(ui::PlatformWindowInitProperties{
                                                  gfx::Rect(0, 0, 100, 100)})
                           .release();
  h2->InitHost();
  h2->window()->Show();
  DeleteHostFromHeldMouseEventDelegate delegate(h2);
  // Owned by |h2|.
  Window* w1 = CreateNormalWindow(1, h2->window(), &delegate);
  w1->SetBounds(gfx::Rect(0, 0, 40, 40));
  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                         gfx::Point(10, 10), ui::EventTimeForNow(),
                         ui::EF_SHIFT_DOWN, 0);
  h2->dispatcher()->RepostEvent(&pressed);
  // RunAllPendingInMessageLoop() to make sure the |pressed| is run.
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(delegate.got_mouse_event());
  EXPECT_TRUE(delegate.got_destroy());
}

TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveTouches) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));

  gfx::Point position1 = root_window()->bounds().origin();
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, position1, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);

  EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN",
            EventTypesToString(recorder.GetAndResetEvents()));

  window->Hide();

  EXPECT_EQ(ui::ET_TOUCH_CANCELLED, recorder.events()[0]);
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_TAP_CANCEL));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_END));
  EXPECT_EQ(3U, recorder.events().size());
  root_window()->RemovePreTargetHandler(&recorder);
}

TEST_F(WindowEventDispatcherTest, WindowHideCancelsActiveGestures) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window()));

  gfx::Point position1 = root_window()->bounds().origin();
  gfx::Point position2 = root_window()->bounds().CenterPoint();
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, position1, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);

  ui::TouchEvent move(
      ui::ET_TOUCH_MOVED, position2, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&move);

  ui::TouchEvent press2(
      ui::ET_TOUCH_PRESSED, position1, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1));
  DispatchEventUsingWindowDispatcher(&press2);

  // TODO(tdresser): once the unified Gesture Recognizer has stuck, remove the
  // special casing here. See crbug.com/332418 for details.
  std::string expected =
      "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
      "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
      "TOUCH_PRESSED GESTURE_BEGIN GESTURE_PINCH_BEGIN";

  std::string expected_ugr =
      "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
      "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
      "TOUCH_PRESSED GESTURE_BEGIN";

  std::string events_string = EventTypesToString(recorder.GetAndResetEvents());
  EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));

  window->Hide();

  expected =
      "TOUCH_CANCELLED GESTURE_PINCH_END GESTURE_END TOUCH_CANCELLED "
      "GESTURE_SCROLL_END GESTURE_END";
  expected_ugr =
      "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END TOUCH_CANCELLED "
      "GESTURE_END";

  events_string = EventTypesToString(recorder.GetAndResetEvents());
  EXPECT_TRUE((expected == events_string) || (expected_ugr == events_string));

  root_window()->RemovePreTargetHandler(&recorder);
}

// Places two windows side by side.  Starts a pinch in one window, then sets
// capture to the other window.  Ensures that subsequent pinch events are
// sent to the window which gained capture.
TEST_F(WindowEventDispatcherTest, TouchpadPinchEventsRetargetOnCapture) {
  EventFilterRecorder recorder1;
  EventFilterRecorder recorder2;
  std::unique_ptr<Window> window1(
      CreateNormalWindow(1, root_window(), nullptr));
  window1->SetBounds(gfx::Rect(0, 0, 40, 40));

  std::unique_ptr<Window> window2(
      CreateNormalWindow(2, root_window(), nullptr));
  window2->SetBounds(gfx::Rect(40, 0, 40, 40));

  window1->AddPreTargetHandler(&recorder1);
  window2->AddPreTargetHandler(&recorder2);

  gfx::Point position1 = window1->bounds().CenterPoint();

  ui::GestureEventDetails begin_details(ui::ET_GESTURE_PINCH_BEGIN);
  begin_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
  ui::GestureEvent begin(position1.x(), position1.y(), 0, ui::EventTimeForNow(),
                         begin_details);
  DispatchEventUsingWindowDispatcher(&begin);

  window2->SetCapture();

  ui::GestureEventDetails update_details(ui::ET_GESTURE_PINCH_UPDATE);
  update_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
  ui::GestureEvent update(position1.x(), position1.y(), 0,
                          ui::EventTimeForNow(), update_details);
  DispatchEventUsingWindowDispatcher(&update);

  ui::GestureEventDetails end_details(ui::ET_GESTURE_PINCH_END);
  end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
  ui::GestureEvent end(position1.x(), position1.y(), 0, ui::EventTimeForNow(),
                       end_details);
  DispatchEventUsingWindowDispatcher(&end);

  EXPECT_EQ("GESTURE_PINCH_BEGIN", EventTypesToString(recorder1.events()));

  EXPECT_EQ("GESTURE_PINCH_UPDATE GESTURE_PINCH_END",
            EventTypesToString(recorder2.events()));
  window1->RemovePreTargetHandler(&recorder1);
  window2->RemovePreTargetHandler(&recorder2);
}

// Places two windows side by side. Presses down on one window, and starts a
// scroll. Sets capture on the other window and ensures that the "ending" events
// aren't sent to the window which gained capture.
TEST_F(WindowEventDispatcherTest, EndingEventDoesntRetarget) {
  EventFilterRecorder recorder1;
  EventFilterRecorder recorder2;
  std::unique_ptr<Window> window1(CreateNormalWindow(1, root_window(), NULL));
  window1->SetBounds(gfx::Rect(0, 0, 40, 40));

  std::unique_ptr<Window> window2(CreateNormalWindow(2, root_window(), NULL));
  window2->SetBounds(gfx::Rect(40, 0, 40, 40));

  window1->AddPreTargetHandler(&recorder1);
  window2->AddPreTargetHandler(&recorder2);

  gfx::Point position = window1->bounds().origin();
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, position, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);

  gfx::Point position2 = window1->bounds().CenterPoint();
  ui::TouchEvent move(
      ui::ET_TOUCH_MOVED, position2, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&move);

  window2->SetCapture();

  EXPECT_EQ("TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED "
            "GESTURE_TAP_CANCEL GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE "
            "TOUCH_CANCELLED GESTURE_SCROLL_END GESTURE_END",
            EventTypesToString(recorder1.events()));

  EXPECT_TRUE(recorder2.events().empty());

  window1->RemovePreTargetHandler(&recorder1);
  window2->RemovePreTargetHandler(&recorder2);
}

namespace {

// This class creates and manages a window which is destroyed as soon as
// capture is lost. This is the case for the drag and drop capture window.
class CaptureWindowTracker : public test::TestWindowDelegate {
 public:
  CaptureWindowTracker() {}
  ~CaptureWindowTracker() override {}

  void CreateCaptureWindow(aura::Window* root_window) {
    capture_window_.reset(test::CreateTestWindowWithDelegate(
        this, -1234, gfx::Rect(20, 20, 20, 20), root_window));
    capture_window_->SetCapture();
  }

  void reset() {
    capture_window_.reset();
  }

  void OnCaptureLost() override { capture_window_.reset(); }

  void OnWindowDestroyed(Window* window) override {
    TestWindowDelegate::OnWindowDestroyed(window);
    capture_window_.reset();
  }

  aura::Window* capture_window() { return capture_window_.get(); }

 private:
  std::unique_ptr<aura::Window> capture_window_;

  DISALLOW_COPY_AND_ASSIGN(CaptureWindowTracker);
};

}

// Verifies handling loss of capture by the capture window being hidden.
TEST_F(WindowEventDispatcherTest, CaptureWindowHidden) {
  CaptureWindowTracker capture_window_tracker;
  capture_window_tracker.CreateCaptureWindow(root_window());
  capture_window_tracker.capture_window()->Hide();
  EXPECT_EQ(NULL, capture_window_tracker.capture_window());
}

// Verifies handling loss of capture by the capture window being destroyed.
TEST_F(WindowEventDispatcherTest, CaptureWindowDestroyed) {
  CaptureWindowTracker capture_window_tracker;
  capture_window_tracker.CreateCaptureWindow(root_window());
  capture_window_tracker.reset();
  EXPECT_EQ(NULL, capture_window_tracker.capture_window());
}

namespace {

class RunLoopHandler : public ui::EventHandler {
 public:
  explicit RunLoopHandler(aura::Window* target)
      : run_loop_(base::RunLoop::Type::kNestableTasksAllowed), target_(target) {
    target_->AddPreTargetHandler(this);
  }
  ~RunLoopHandler() override { target_->RemovePreTargetHandler(this); }
  int num_scroll_updates() const { return num_scroll_updates_; }

 private:
  // ui::EventHandler:
  void OnGestureEvent(ui::GestureEvent* event) override {
    if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE)
      return;
    num_scroll_updates_++;
    if (running_) {
      run_loop_.QuitWhenIdle();
    } else {
      running_ = true;
      run_loop_.Run();
    }
  }

  base::RunLoop run_loop_;
  bool running_ = false;
  int num_scroll_updates_ = 0;

  aura::Window* target_;

  DISALLOW_COPY_AND_ASSIGN(RunLoopHandler);
};

}  // namespace

TEST_F(WindowEventDispatcherTest, HeldTouchMoveWithRunLoop) {
  RunLoopHandler handler(root_window());

  host()->dispatcher()->HoldPointerMoves();

  gfx::Point point = root_window()->GetBoundsInScreen().CenterPoint();
  ui::TouchEvent ev0(ui::ET_TOUCH_PRESSED, point, ui::EventTimeForNow(),
                     ui::PointerDetails());
  DispatchEventUsingWindowDispatcher(&ev0);

  point.Offset(10, 10);
  ui::TouchEvent ev1(ui::ET_TOUCH_MOVED, point, ui::EventTimeForNow(),
                     ui::PointerDetails());
  DispatchEventUsingWindowDispatcher(&ev1);
  // The move event is held, so SCROLL_UPDATE does not happen yet.
  EXPECT_EQ(0, handler.num_scroll_updates());

  // ReleasePointerMoves() will post DispatchHeldEvent() asynchronously.
  host()->dispatcher()->ReleasePointerMoves();
  point.Offset(10, 10);
  // Schedule another move event which should cause another SCROLL_UPDATE and
  // quit the run_loop within the handler.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindLambdaForTesting([&]() {
        ui::TouchEvent ev2(ui::ET_TOUCH_MOVED, point, base::TimeTicks::Now(),
                           ui::PointerDetails());
        DispatchEventUsingWindowDispatcher(&ev2);
      }));
  // Wait for both DispatchHeldEvent() and dispatch of |ev2|.
  base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();

  // Makes sure that the run_loop ran and then ended.
  EXPECT_EQ(2, handler.num_scroll_updates());
}

class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler {
 public:
  ExitMessageLoopOnMousePress() {}
  ~ExitMessageLoopOnMousePress() override {}

 protected:
  void OnMouseEvent(ui::MouseEvent* event) override {
    ui::test::TestEventHandler::OnMouseEvent(event);
    if (event->type() == ui::ET_MOUSE_PRESSED)
      base::RunLoop::QuitCurrentWhenIdleDeprecated();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ExitMessageLoopOnMousePress);
};

class WindowEventDispatcherTestWithMessageLoop
    : public WindowEventDispatcherTest {
 public:
  WindowEventDispatcherTestWithMessageLoop() {}
  ~WindowEventDispatcherTestWithMessageLoop() override {}

  void RunTest() {
    // Reset any event the window may have received when bringing up the window
    // (e.g. mouse-move events if the mouse cursor is over the window).
    handler_.Reset();

    base::RunLoop loop(base::RunLoop::Type::kNestableTasksAllowed);

    // Start a nested message-loop, post an event to be dispatched, and then
    // terminate the message-loop. When the message-loop unwinds and gets back,
    // the reposted event should not have fired.
    std::unique_ptr<ui::MouseEvent> mouse(new ui::MouseEvent(
        ui::ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(10, 10),
        ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE));
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &WindowEventDispatcherTestWithMessageLoop::RepostEventHelper,
            host()->dispatcher(), std::move(mouse)));
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  loop.QuitWhenIdleClosure());

    loop.Run();
    EXPECT_EQ(0, handler_.num_mouse_events());

    // Let the current message-loop run. The event-handler will terminate the
    // message-loop when it receives the reposted event.
  }

 protected:
  void SetUp() override {
    WindowEventDispatcherTest::SetUp();
    window_.reset(CreateNormalWindow(1, root_window(), NULL));
    window_->AddPreTargetHandler(&handler_);
  }

  void TearDown() override {
    window_->RemovePreTargetHandler(&handler_);
    window_.reset();
    WindowEventDispatcherTest::TearDown();
  }

 private:
  // Used to avoid a copying |event| when binding to a closure.
  static void RepostEventHelper(WindowEventDispatcher* dispatcher,
                                std::unique_ptr<ui::MouseEvent> event) {
    dispatcher->RepostEvent(event.get());
  }

  std::unique_ptr<Window> window_;
  ExitMessageLoopOnMousePress handler_;

  DISALLOW_COPY_AND_ASSIGN(WindowEventDispatcherTestWithMessageLoop);
};

TEST_F(WindowEventDispatcherTestWithMessageLoop, EventRepostedInNonNestedLoop) {
  ASSERT_FALSE(base::RunLoop::IsRunningOnCurrentThread());
  // Perform the test in a callback, so that it runs after the message-loop
  // starts.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&WindowEventDispatcherTestWithMessageLoop::RunTest,
                     base::Unretained(this)));
  base::RunLoop().Run();
}

class WindowEventDispatcherTestInHighDPI : public WindowEventDispatcherTest {
 public:
  WindowEventDispatcherTestInHighDPI() {}
  ~WindowEventDispatcherTestInHighDPI() override {}

  void DispatchEvent(ui::Event* event) {
    DispatchEventUsingWindowDispatcher(event);
  }

 protected:
  void SetUp() override {
    WindowEventDispatcherTest::SetUp();
    test_screen()->SetDeviceScaleFactor(2.f);
  }
};

TEST_F(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<aura::Window> child(test::CreateTestWindowWithDelegate(
      &delegate, 1234, gfx::Rect(20, 20, 100, 100), root_window()));
  child->Show();

  ui::test::TestEventHandler handler_child;
  ui::test::TestEventHandler handler_root;
  root_window()->AddPreTargetHandler(&handler_root);
  child->AddPreTargetHandler(&handler_child);

  {
    ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(30, 30),
                        gfx::Point(30, 30), ui::EventTimeForNow(), ui::EF_NONE,
                        ui::EF_NONE);
    DispatchEventUsingWindowDispatcher(&move);
    EXPECT_EQ(0, handler_child.num_mouse_events());
    EXPECT_EQ(1, handler_root.num_mouse_events());
  }

  {
    ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
                        gfx::Point(50, 50), ui::EventTimeForNow(), ui::EF_NONE,
                        ui::EF_NONE);
    DispatchEventUsingWindowDispatcher(&move);
    // The child receives an ENTER, and a MOVED event.
    EXPECT_EQ(2, handler_child.num_mouse_events());
    // The root receives both the ENTER and the MOVED events dispatched to
    // |child|, as well as an EXIT event.
    EXPECT_EQ(3, handler_root.num_mouse_events());
  }

  child->RemovePreTargetHandler(&handler_child);
  root_window()->RemovePreTargetHandler(&handler_root);
}

TEST_F(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);
  test::TestWindowDelegate delegate;
  HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
  window->AddPreTargetHandler(&handler);

  ui::test::EventGenerator generator(root_window());
  generator.GestureScrollSequence(
      gfx::Point(120, 120), gfx::Point(20, 120),
      base::TimeDelta::FromMilliseconds(100), 25);

  // |handler| will have reset |filter| and started holding the touch-move
  // events when scrolling started. At the end of the scroll (i.e. upon
  // touch-release), the held touch-move event will have been dispatched first,
  // along with the subsequent events (i.e. touch-release, scroll-end, and
  // gesture-end).
  const EventFilterRecorder::Events& events = recorder.events();
  EXPECT_EQ(
      "TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED "
      "GESTURE_SCROLL_END GESTURE_END",
      EventTypesToString(events));
  ASSERT_EQ(2u, recorder.touch_locations().size());
  EXPECT_EQ(gfx::Point(-40, 10).ToString(),
            recorder.touch_locations()[0].ToString());
  EXPECT_EQ(gfx::Point(-40, 10).ToString(),
            recorder.touch_locations()[1].ToString());
  root_window()->RemovePreTargetHandler(&recorder);
  window->RemovePreTargetHandler(&handler);
}

// This handler triggers a nested run loop when it receives a right click
// event, and runs a single callback in the nested run loop.
class TriggerNestedLoopOnRightMousePress : public ui::test::TestEventHandler {
 public:
  explicit TriggerNestedLoopOnRightMousePress(const base::Closure& callback)
      : callback_(callback) {}
  ~TriggerNestedLoopOnRightMousePress() override {}

  const gfx::Point mouse_move_location() const { return mouse_move_location_; }

 private:
  void OnMouseEvent(ui::MouseEvent* mouse) override {
    TestEventHandler::OnMouseEvent(mouse);
    if (mouse->type() == ui::ET_MOUSE_PRESSED &&
        mouse->IsOnlyRightMouseButton()) {
      base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
      scoped_refptr<base::TaskRunner> task_runner =
          base::ThreadTaskRunnerHandle::Get();
      if (!callback_.is_null())
        task_runner->PostTask(FROM_HERE, callback_);
      task_runner->PostTask(FROM_HERE, run_loop.QuitClosure());
      run_loop.Run();
    } else if (mouse->type() == ui::ET_MOUSE_MOVED) {
      mouse_move_location_ = mouse->location();
    }
  }

  base::Closure callback_;
  gfx::Point mouse_move_location_;

  DISALLOW_COPY_AND_ASSIGN(TriggerNestedLoopOnRightMousePress);
};

// Tests that if dispatching a 'held' event triggers a nested run loop, then
// the events that are dispatched from the nested run loop are transformed
// correctly.
TEST_F(WindowEventDispatcherTestInHighDPI,
       EventsTransformedInRepostedEventTriggeredNestedLoop) {
  std::unique_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
  // Make sure the window is visible.
  RunAllPendingInMessageLoop();

  ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, gfx::Point(80, 80),
                            gfx::Point(80, 80), ui::EventTimeForNow(),
                            ui::EF_NONE, ui::EF_NONE);
  const base::Closure callback_on_right_click = base::Bind(
      base::IgnoreResult(&WindowEventDispatcherTestInHighDPI::DispatchEvent),
      base::Unretained(this), base::Unretained(&mouse_move));
  TriggerNestedLoopOnRightMousePress handler(callback_on_right_click);
  window->AddPreTargetHandler(&handler);

  std::unique_ptr<ui::MouseEvent> mouse(
      new ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(10, 10),
                         gfx::Point(10, 10), ui::EventTimeForNow(),
                         ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON));
  host()->dispatcher()->RepostEvent(mouse.get());
  EXPECT_EQ(0, handler.num_mouse_events());

  base::RunLoop run_loop;
  run_loop.RunUntilIdle();
  // The window should receive the mouse-press and the mouse-move events.
  EXPECT_EQ(2, handler.num_mouse_events());
  // The mouse-move event location should be transformed because of the DSF
  // before it reaches the window.
  EXPECT_EQ(gfx::Point(40, 40).ToString(),
            handler.mouse_move_location().ToString());
  EXPECT_EQ(gfx::Point(40, 40).ToString(),
            Env::GetInstance()->last_mouse_location().ToString());
  window->RemovePreTargetHandler(&handler);
}

class SelfDestructDelegate : public test::TestWindowDelegate {
 public:
  SelfDestructDelegate() {}
  ~SelfDestructDelegate() override {}

  void OnMouseEvent(ui::MouseEvent* event) override { window_.reset(); }

  void set_window(std::unique_ptr<aura::Window> window) {
    window_ = std::move(window);
  }
  bool has_window() const { return !!window_.get(); }

 private:
  std::unique_ptr<aura::Window> window_;
  DISALLOW_COPY_AND_ASSIGN(SelfDestructDelegate);
};

TEST_F(WindowEventDispatcherTest, SynthesizedLocatedEvent) {
  ui::test::EventGenerator generator(root_window());
  generator.MoveMouseTo(10, 10);
  EXPECT_EQ("10,10",
            Env::GetInstance()->last_mouse_location().ToString());

  // Synthesized event should not update the mouse location.
  ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
                         ui::EventTimeForNow(), ui::EF_IS_SYNTHESIZED, 0);
  generator.Dispatch(&mouseev);
  EXPECT_EQ("10,10",
            Env::GetInstance()->last_mouse_location().ToString());

  generator.MoveMouseTo(0, 0);
  EXPECT_EQ("0,0",
            Env::GetInstance()->last_mouse_location().ToString());

  // Make sure the location gets updated when a syntheiszed enter
  // event destroyed the window.
  SelfDestructDelegate delegate;
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(50, 50, 100, 100), root_window()));
  delegate.set_window(std::move(window));
  EXPECT_TRUE(delegate.has_window());

  generator.MoveMouseTo(100, 100);
  EXPECT_FALSE(delegate.has_window());
  EXPECT_EQ("100,100",
            Env::GetInstance()->last_mouse_location().ToString());
}

// Tests that the window which has capture can get destroyed as a result of
// ui::ET_MOUSE_CAPTURE_CHANGED event dispatched in
// WindowEventDispatcher::UpdateCapture without causing a "use after free".
TEST_F(WindowEventDispatcherTest, DestroyWindowOnCaptureChanged) {
  SelfDestructDelegate delegate;
  std::unique_ptr<aura::Window> window_first(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(20, 10, 10, 20), root_window()));
  Window* window_first_raw = window_first.get();
  window_first->Show();
  window_first->SetCapture();
  delegate.set_window(std::move(window_first));
  EXPECT_TRUE(delegate.has_window());

  std::unique_ptr<aura::Window> window_second(
      test::CreateTestWindowWithId(2, root_window()));
  window_second->Show();

  client::CaptureDelegate* capture_delegate = host()->dispatcher();
  capture_delegate->UpdateCapture(window_first_raw, window_second.get());
  EXPECT_FALSE(delegate.has_window());
}

class StaticFocusClient : public client::FocusClient {
 public:
  explicit StaticFocusClient(Window* focused)
      : focused_(focused) {}
  ~StaticFocusClient() override {}

 private:
  // client::FocusClient:
  void AddObserver(client::FocusChangeObserver* observer) override {}
  void RemoveObserver(client::FocusChangeObserver* observer) override {}
  void FocusWindow(Window* window) override {}
  void ResetFocusWithinActiveWindow(Window* window) override {}
  Window* GetFocusedWindow() override { return focused_; }

  Window* focused_;

  DISALLOW_COPY_AND_ASSIGN(StaticFocusClient);
};

// Tests that host-cancel-mode event can be dispatched to a dispatcher safely
// when the focused window does not live in the dispatcher's tree.
TEST_F(WindowEventDispatcherTest, HostCancelModeWithFocusedWindowOutside) {
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> focused(CreateTestWindowWithDelegate(
      &delegate, 123, gfx::Rect(20, 30, 100, 50), NULL));
  StaticFocusClient focus_client(focused.get());
  client::SetFocusClient(root_window(), &focus_client);
  EXPECT_FALSE(root_window()->Contains(focused.get()));
  EXPECT_EQ(focused.get(),
            client::GetFocusClient(root_window())->GetFocusedWindow());
  host()->dispatcher()->DispatchCancelModeEvent();
  EXPECT_EQ(focused.get(),
            client::GetFocusClient(root_window())->GetFocusedWindow());
}

// Dispatches a mouse-move event to |target| when it receives a mouse-move
// event.
class DispatchEventHandler : public ui::EventHandler {
 public:
  explicit DispatchEventHandler(Window* target)
      : target_(target),
        dispatched_(false) {}
  ~DispatchEventHandler() override {}

  bool dispatched() const { return dispatched_; }
 private:
  // ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* mouse) override {
    if (mouse->type() == ui::ET_MOUSE_MOVED) {
      ui::MouseEvent move(ui::ET_MOUSE_MOVED, target_->bounds().CenterPoint(),
                          target_->bounds().CenterPoint(),
                          ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
      ui::EventDispatchDetails details =
          target_->GetHost()->dispatcher()->OnEventFromSource(&move);
      ASSERT_FALSE(details.dispatcher_destroyed);
      EXPECT_FALSE(details.target_destroyed);
      EXPECT_EQ(target_, move.target());
      dispatched_ = true;
    }
    ui::EventHandler::OnMouseEvent(mouse);
  }

  Window* target_;
  bool dispatched_;

  DISALLOW_COPY_AND_ASSIGN(DispatchEventHandler);
};

// Moves |window| to |root_window| when it receives a mouse-move event.
class MoveWindowHandler : public ui::EventHandler {
 public:
  MoveWindowHandler(Window* window, Window* root_window)
      : window_to_move_(window),
        root_window_to_move_to_(root_window) {}
  ~MoveWindowHandler() override {}

 private:
  // ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* mouse) override {
    if (mouse->type() == ui::ET_MOUSE_MOVED) {
      root_window_to_move_to_->AddChild(window_to_move_);
    }
    ui::EventHandler::OnMouseEvent(mouse);
  }

  Window* window_to_move_;
  Window* root_window_to_move_to_;

  DISALLOW_COPY_AND_ASSIGN(MoveWindowHandler);
};

// Tests that nested event dispatch works correctly if the target of the older
// event being dispatched is moved to a different dispatcher in response to an
// event in the inner loop.
TEST_F(WindowEventDispatcherTest, NestedEventDispatchTargetMoved) {
  std::unique_ptr<WindowTreeHost> second_host = WindowTreeHost::Create(
      ui::PlatformWindowInitProperties{gfx::Rect(20, 30, 100, 50)});
  second_host->InitHost();
  second_host->window()->Show();
  Window* second_root = second_host->window();

  // Create two windows parented to |root_window()|.
  test::TestWindowDelegate delegate;
  std::unique_ptr<Window> first(CreateTestWindowWithDelegate(
      &delegate, 123, gfx::Rect(20, 10, 10, 20), root_window()));
  std::unique_ptr<Window> second(CreateTestWindowWithDelegate(
      &delegate, 234, gfx::Rect(40, 10, 50, 20), root_window()));

  // Setup a handler on |first| so that it dispatches an event to |second| when
  // |first| receives an event.
  DispatchEventHandler dispatch_event(second.get());
  first->AddPreTargetHandler(&dispatch_event);

  // Setup a handler on |second| so that it moves |first| into |second_root|
  // when |second| receives an event.
  MoveWindowHandler move_window(first.get(), second_root);
  second->AddPreTargetHandler(&move_window);

  // Some sanity checks: |first| is inside |root_window()|'s tree.
  EXPECT_EQ(root_window(), first->GetRootWindow());
  // The two root windows are different.
  EXPECT_NE(root_window(), second_root);

  // Dispatch an event to |first|.
  ui::MouseEvent move(ui::ET_MOUSE_MOVED, first->bounds().CenterPoint(),
                      first->bounds().CenterPoint(), ui::EventTimeForNow(),
                      ui::EF_NONE, ui::EF_NONE);
  ui::EventDispatchDetails details =
      host()->dispatcher()->OnEventFromSource(&move);
  ASSERT_FALSE(details.dispatcher_destroyed);
  EXPECT_TRUE(details.target_destroyed);
  EXPECT_EQ(first.get(), move.target());
  EXPECT_TRUE(dispatch_event.dispatched());
  EXPECT_EQ(second_root, first->GetRootWindow());

  first->RemovePreTargetHandler(&dispatch_event);
  second->RemovePreTargetHandler(&move_window);
}

class AlwaysMouseDownInputStateLookup : public InputStateLookup {
 public:
  AlwaysMouseDownInputStateLookup() {}
  ~AlwaysMouseDownInputStateLookup() override {}

 private:
  // InputStateLookup:
  bool IsMouseButtonDown() const override { return true; }

  DISALLOW_COPY_AND_ASSIGN(AlwaysMouseDownInputStateLookup);
};

TEST_F(WindowEventDispatcherTest,
       CursorVisibilityChangedWhileCaptureWindowInAnotherDispatcher) {
  test::EventCountDelegate delegate;
  std::unique_ptr<Window> window(CreateTestWindowWithDelegate(
      &delegate, 123, gfx::Rect(20, 10, 10, 20), root_window()));
  window->Show();

  std::unique_ptr<WindowTreeHost> second_host = WindowTreeHost::Create(
      ui::PlatformWindowInitProperties{gfx::Rect(20, 30, 100, 50)});
  second_host->InitHost();
  second_host->window()->Show();
  WindowEventDispatcher* second_dispatcher = second_host->dispatcher();

  // Install an InputStateLookup on the Env that always claims that a
  // mouse-button is down.
  test::EnvTestHelper(Env::GetInstance())
      .SetInputStateLookup(std::unique_ptr<InputStateLookup>(
          new AlwaysMouseDownInputStateLookup()));

  window->SetCapture();

  // Because the mouse button is down, setting the capture on |window| will set
  // it as the mouse-move handler for |root_window()|.
  EXPECT_EQ(window.get(), host()->dispatcher()->mouse_moved_handler());

  // This does not set |window| as the mouse-move handler for the second
  // dispatcher.
  EXPECT_EQ(NULL, second_dispatcher->mouse_moved_handler());

  // However, some capture-client updates the capture in each root-window on a
  // capture. Emulate that here. Because of this, the second dispatcher also has
  // |window| as the mouse-move handler.
  client::CaptureDelegate* second_capture_delegate = second_dispatcher;
  second_capture_delegate->UpdateCapture(NULL, window.get());
  EXPECT_EQ(window.get(), second_dispatcher->mouse_moved_handler());

  // Reset the mouse-event counts for |window|.
  delegate.GetMouseMotionCountsAndReset();

  // Notify both hosts that the cursor is now hidden. This should send a single
  // mouse-exit event to |window|.
  host()->OnCursorVisibilityChanged(false);
  second_host->OnCursorVisibilityChanged(false);
  EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset());
}

TEST_F(WindowEventDispatcherTest,
       RedirectedEventToDifferentDispatcherLocation) {
  std::unique_ptr<WindowTreeHost> second_host = WindowTreeHost::Create(
      ui::PlatformWindowInitProperties{gfx::Rect(20, 30, 100, 50)});
  second_host->InitHost();
  second_host->window()->Show();
  client::SetCaptureClient(second_host->window(),
                           client::GetCaptureClient(root_window()));

  test::EventCountDelegate delegate;
  std::unique_ptr<Window> window_first(CreateTestWindowWithDelegate(
      &delegate, 123, gfx::Rect(20, 10, 10, 20), root_window()));
  window_first->Show();

  std::unique_ptr<Window> window_second(CreateTestWindowWithDelegate(
      &delegate, 12, gfx::Rect(10, 10, 20, 30), second_host->window()));
  window_second->Show();

  window_second->SetCapture();
  EXPECT_EQ(window_second.get(),
            client::GetCaptureWindow(root_window()));

  // Send an event to the first host. Make sure it goes to |window_second| in
  // |second_host| instead (since it has capture).
  EventFilterRecorder recorder_first;
  window_first->AddPreTargetHandler(&recorder_first);
  EventFilterRecorder recorder_second;
  window_second->AddPreTargetHandler(&recorder_second);
  const gfx::Point event_location(25, 15);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, event_location, event_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_TRUE(recorder_first.events().empty());
  ASSERT_EQ(1u, recorder_second.events().size());
  EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder_second.events()[0]);
  EXPECT_EQ(event_location.ToString(),
            recorder_second.mouse_locations()[0].ToString());
  window_first->RemovePreTargetHandler(&recorder_first);
  window_second->RemovePreTargetHandler(&recorder_second);
}

class AsyncWindowDelegate : public test::TestWindowDelegate {
 public:
  AsyncWindowDelegate(WindowEventDispatcher* dispatcher)
      : dispatcher_(dispatcher), window_(nullptr) {}

  void set_window(Window* window) {
    window_ = window;
  }
 private:
  void OnTouchEvent(ui::TouchEvent* event) override {
    // Convert touch event back to root window coordinates.
    event->ConvertLocationToTarget(window_, window_->GetRootWindow());
    event->DisableSynchronousHandling();
    dispatcher_->ProcessedTouchEvent(
        event->unique_event_id(), window_, ui::ER_UNHANDLED,
        false /* is_source_touch_event_set_non_blocking */);
    event->StopPropagation();
  }

  WindowEventDispatcher* dispatcher_;
  Window* window_;

  DISALLOW_COPY_AND_ASSIGN(AsyncWindowDelegate);
};

// Tests that gesture events dispatched through the asynchronous flow have
// co-ordinates in the right co-ordinate space.
TEST_F(WindowEventDispatcherTest, GestureEventCoordinates) {
  const float kX = 67.3f;
  const float kY = 97.8f;

  const int kWindowOffset = 50;
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);
  AsyncWindowDelegate delegate(host()->dispatcher());
  HoldPointerOnScrollHandler handler(host()->dispatcher(), &recorder);
  std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
      &delegate, 1, gfx::Rect(kWindowOffset, kWindowOffset, 100, 100),
      root_window()));
  window->AddPreTargetHandler(&handler);

  delegate.set_window(window.get());

  ui::TouchEvent touch_pressed_event(
      ui::ET_TOUCH_PRESSED, gfx::Point(), ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  touch_pressed_event.set_location_f(gfx::PointF(kX, kY));
  touch_pressed_event.set_root_location_f(gfx::PointF(kX, kY));

  DispatchEventUsingWindowDispatcher(&touch_pressed_event);

  ASSERT_EQ(1u, recorder.touch_locations().size());
  EXPECT_EQ(gfx::Point(kX - kWindowOffset, kY - kWindowOffset).ToString(),
            recorder.touch_locations()[0].ToString());

  ASSERT_EQ(2u, recorder.gesture_locations().size());
  EXPECT_EQ(gfx::Point(kX - kWindowOffset, kY - kWindowOffset).ToString(),
            recorder.gesture_locations()[0].ToString());
  root_window()->RemovePreTargetHandler(&recorder);
  window->RemovePreTargetHandler(&handler);
}

// Tests that a scroll-generating touch-event is marked as such.
TEST_F(WindowEventDispatcherTest, TouchMovesMarkedWhenCausingScroll) {
  EventFilterRecorder recorder;
  root_window()->AddPreTargetHandler(&recorder);

  const gfx::Point location(20, 20);
  ui::TouchEvent press(
      ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_FALSE(recorder.LastTouchMayCauseScrolling());
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_PRESSED));
  recorder.Reset();

  ui::TouchEvent move(
      ui::ET_TOUCH_MOVED, location + gfx::Vector2d(100, 100),
      ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&move);
  EXPECT_TRUE(recorder.LastTouchMayCauseScrolling());
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_BEGIN));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_UPDATE));
  recorder.Reset();

  ui::TouchEvent move2(
      ui::ET_TOUCH_MOVED, location + gfx::Vector2d(200, 200),
      ui::EventTimeForNow(),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&move2);
  EXPECT_TRUE(recorder.LastTouchMayCauseScrolling());
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_MOVED));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_UPDATE));
  recorder.Reset();

  // Delay the release to avoid fling generation.
  ui::TouchEvent release(
      ui::ET_TOUCH_RELEASED, location + gfx::Vector2d(200, 200),
      ui::EventTimeForNow() + base::TimeDelta::FromSeconds(1),
      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
  DispatchEventUsingWindowDispatcher(&release);
  EXPECT_TRUE(recorder.LastTouchMayCauseScrolling());
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_RELEASED));
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_END));

  root_window()->RemovePreTargetHandler(&recorder);
}

// OnCursorMovedToRootLocation() is sometimes called instead of
// WindowTreeHost::MoveCursorTo() when the cursor did not move but the
// cursor's position in root coordinates has changed (e.g. when the displays's
// scale factor changed). Test that hover effects are properly updated.
TEST_F(WindowEventDispatcherTest, OnCursorMovedToRootLocationUpdatesHover) {
  WindowEventDispatcher* dispatcher = host()->dispatcher();
  test::TestCursorClient cursor_client(root_window());
  cursor_client.ShowCursor();

  std::unique_ptr<Window> w(CreateNormalWindow(1, root_window(), nullptr));
  w->SetBounds(gfx::Rect(20, 20, 20, 20));
  w->Show();

  // Move the cursor off of |w|.
  dispatcher->OnCursorMovedToRootLocation(gfx::Point(100, 100));

  EventFilterRecorder recorder;
  w->AddPreTargetHandler(&recorder);
  dispatcher->OnCursorMovedToRootLocation(gfx::Point(22, 22));
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_MOUSE_ENTERED));
  recorder.Reset();

  // The cursor should not be over |w| after changing the device scale factor to
  // 2x. A ET_MOUSE_EXITED event should have been sent to |w|.
  test_screen()->SetDeviceScaleFactor(2.f);
  dispatcher->OnCursorMovedToRootLocation(gfx::Point(11, 11));
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_MOUSE_EXITED));
  recorder.Reset();

  // Hide the cursor, synthetic event will not be sent.
  cursor_client.HideCursor();
  dispatcher->OnCursorMovedToRootLocation(gfx::Point(22, 22));
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.events().empty());

  // Cursor is hidden when locked, but synthetic move event still be dispatched.
  cursor_client.LockCursor();
  dispatcher->OnCursorMovedToRootLocation(gfx::Point(33, 33));
  RunAllPendingInMessageLoop();
  EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_MOUSE_MOVED));
  recorder.Reset();

  w->RemovePreTargetHandler(&recorder);
}

// Tests that we correctly report the fraction of time without user input via
// UMA.
TEST_F(WindowEventDispatcherTest, FractionOfTimeWithoutUserInputRecorded) {
  const char* kHistogram = "Event.FractionOfTimeWithoutUserInput";
  base::HistogramTester tester;

  std::unique_ptr<aura::Window> window(
      test::CreateTestWindowWithId(1234, root_window()));

  ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeStampFromSeconds(4), 0,
                        0);

  // To flush the idle fraction reporter, we need to dispatch two events. The
  // first event causes us to record the previous active period, and the second
  // flushes the previous active period.
  ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeStampFromSeconds(16),
                        0, 0);

  ui::MouseEvent mouse3(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
                        gfx::Point(10, 10), ui::EventTimeStampFromSeconds(30),
                        0, 0);

  DispatchEventUsingWindowDispatcher(&mouse1);
  DispatchEventUsingWindowDispatcher(&mouse2);
  DispatchEventUsingWindowDispatcher(&mouse3);

  tester.ExpectTotalCount(kHistogram, 1);
}

TEST_F(WindowEventDispatcherTest, TouchEventWithScaledWindow) {
  WindowEventDispatcher* dispatcher = host()->dispatcher();

  EventFilterRecorder root_recorder;
  root_window()->AddPreTargetHandler(&root_recorder);

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

  const gfx::Point child_position(-10, -10);
  const gfx::Rect& root_bounds = root_window()->bounds();
  gfx::Rect child_bounds(child_position,
                         gfx::ScaleToCeiledSize(root_bounds.size(), 2));
  child->SetBounds(child_bounds);
  gfx::Transform transform;
  transform.Scale(0.5, 0.5);
  child->SetTransform(transform);

  EventFilterRecorder child_recorder;
  child->AddPreTargetHandler(&child_recorder);

  std::string expected_events =
      "TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_RELEASED "
      "GESTURE_SHOW_PRESS GESTURE_TAP GESTURE_END";
  {
    // Touch events are outside of the root window, but inside of the child
    // window.
    const gfx::Point touch_position(-5, -5);
    ui::TouchEvent pressed_event(
        ui::ET_TOUCH_PRESSED, touch_position, ui::EventTimeForNow(),
        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
    ui::TouchEvent released_event(
        ui::ET_TOUCH_RELEASED, touch_position, ui::EventTimeForNow(),
        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
    dispatcher->OnEventFromSource(&pressed_event);
    dispatcher->OnEventFromSource(&released_event);
    EXPECT_EQ(expected_events, EventTypesToString(root_recorder.events()));
    EXPECT_EQ("", EventTypesToString(child_recorder.events()));
    root_recorder.Reset();
    child_recorder.Reset();
  }

  {
    // |touch_position| value is in the bounds of both the root window and the
    // child window.
    const gfx::Point touch_position(5, 5);
    ui::TouchEvent pressed_event(
        ui::ET_TOUCH_PRESSED, touch_position, ui::EventTimeForNow(),
        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
    ui::TouchEvent released_event(
        ui::ET_TOUCH_RELEASED, touch_position, ui::EventTimeForNow(),
        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
    dispatcher->OnEventFromSource(&pressed_event);
    dispatcher->OnEventFromSource(&released_event);
    EXPECT_EQ(expected_events, EventTypesToString(root_recorder.events()));
    EXPECT_EQ(expected_events, EventTypesToString(child_recorder.events()));
    root_recorder.Reset();
    child_recorder.Reset();
  }

  child->RemovePreTargetHandler(&child_recorder);
  root_window()->RemovePreTargetHandler(&root_recorder);
}

}  // namespace aura
