// 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 "services/ws/public/mojom/window_tree_constants.mojom.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/mus/window_tree_client.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 HTTOPLEFT;
  }
  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::AuraTestBaseWithType;

TEST_P(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. The expected
  // value is 2 when mode is MUS, since ClientSideWindowMoveHandler also invokes
  // it.
  EXPECT_EQ((Env::GetInstance()->mode() == Env::Mode::MUS) ? 2 : 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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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::ContainsValue(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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(ws::mojom::EventTargetingPolicy::NONE);

  // 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(
      ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
  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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
  // This test is only applicable to LOCAL mode as it's setting a device scale
  // factor and expecting events to be transformed while routing the event
  // directly through host(). In MUS mode the window-service does the scaling.
  if (GetParam() == Env::Mode::MUS)
    return;

  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_P(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
  // This test is only applicable to LOCAL mode as it's setting a device scale
  // factor and expecting events to be transformed while routing the event
  // directly through host(). In MUS mode the window-service does the scaling.
  if (GetParam() == Env::Mode::MUS)
    return;

  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_P(WindowEventDispatcherTestInHighDPI,
       EventsTransformedInRepostedEventTriggeredNestedLoop) {
  // This test is only applicable to LOCAL mode as it's setting a device scale
  // factor and expecting events to be transformed while routing the event
  // directly through host(). In MUS mode the window-service does the scaling.
  if (GetParam() == Env::Mode::MUS)
    return;

  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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(WindowEventDispatcherTest, OnCursorMovedToRootLocationUpdatesHover) {
  // This test is only applicable to LOCAL mode as it's setting a device scale
  // factor and expecting events to be transformed while routing the event
  // directly through host(). In MUS mode the window-service does the scaling.
  if (GetParam() == Env::Mode::MUS)
    return;

  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_P(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_P(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();
  }

  // Classic backend cannot dispatch events with non-null target.
  if (GetParam() != Env::Mode::LOCAL) {
    // |touch_position| value isn't in the bounds of root window, but it is in
    // the bounds of the child window.
    const gfx::Point touch_position =
        root_bounds.bottom_right() + gfx::Vector2d(20, 20);
    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));

    gfx::Point touch_root_position = touch_position;
    aura::Window::ConvertPointToTarget(child.get(), root_window(),
                                       &touch_root_position);
    ui::Event::DispatcherApi(&pressed_event).set_target(child.get());
    pressed_event.set_root_location(touch_root_position);
    ui::Event::DispatcherApi(&released_event).set_target(child.get());
    released_event.set_root_location(touch_position);
    dispatcher->OnEventFromSource(&pressed_event);
    dispatcher->OnEventFromSource(&released_event);

    EXPECT_TRUE(child->bounds().Contains(touch_position));
    EXPECT_FALSE(root_window()->bounds().Contains(touch_position));
    EXPECT_TRUE(root_window()->bounds().Contains(touch_root_position));
    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);
}

INSTANTIATE_TEST_CASE_P(/* no prefix */,
                        WindowEventDispatcherTest,
                        ::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS));

INSTANTIATE_TEST_CASE_P(/* no prefix */,
                        WindowEventDispatcherTestWithMessageLoop,
                        ::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS));

INSTANTIATE_TEST_CASE_P(/* no prefix */,
                        WindowEventDispatcherTestInHighDPI,
                        ::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS));

using WindowEventDispatcherMusTest = test::AuraTestBaseMus;

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

  int mouse_event_count() const { return mouse_event_count_; }
  const gfx::Point& last_mouse_location() const { return last_mouse_location_; }

  // TestWindowDelegate:
  void OnMouseEvent(ui::MouseEvent* event) override {
    ++mouse_event_count_;
    last_mouse_location_ = event->root_location();
    EXPECT_EQ(last_mouse_location_, Env::GetInstance()->last_mouse_location());
  }

 private:
  int mouse_event_count_ = 0;
  gfx::Point last_mouse_location_;

  DISALLOW_COPY_AND_ASSIGN(LastEventLocationDelegate);
};

TEST_F(WindowEventDispatcherMusTest, LastEventLocation) {
  LastEventLocationDelegate last_event_location_delegate;
  std::unique_ptr<Window> window(
      CreateTestWindowWithDelegate(&last_event_location_delegate, 123,
                                   gfx::Rect(0, 0, 10, 20), root_window()));

  // Enable fetching mouse location from mouse.
  test::EnvTestHelper().SetAlwaysUseLastMouseLocation(false);
  EXPECT_EQ(gfx::Point(0, 0),
            window_tree_client_impl()->GetCursorScreenPoint());
  EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());

  // Dispatch an event to |mouse_location|. While dispatching the event
  // Env::last_mouse_location() should return |mouse_location|.
  const gfx::Point mouse_location(1, 2);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(1, last_event_location_delegate.mouse_event_count());
  EXPECT_EQ(mouse_location, last_event_location_delegate.last_mouse_location());

  // After dispatch the location should fallback to that of the
  // WindowTreeClient, which defaults to 0,0.
  EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());
}

TEST_F(WindowEventDispatcherMusTest, UseDefaultTargeterToFindTarget) {
  LastEventLocationDelegate last_event_location_delegate1;
  std::unique_ptr<Window> child1(
      CreateTestWindowWithDelegate(&last_event_location_delegate1, 123,
                                   gfx::Rect(10, 10, 100, 100), root_window()));
  LastEventLocationDelegate last_event_location_delegate2;
  std::unique_ptr<Window> child2(
      CreateTestWindowWithDelegate(&last_event_location_delegate2, 124,
                                   gfx::Rect(20, 30, 100, 100), child1.get()));

  const gfx::Point mouse_location(30, 40);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(0, last_event_location_delegate1.mouse_event_count());
  EXPECT_EQ(1, last_event_location_delegate2.mouse_event_count());
  EXPECT_EQ(gfx::Point(), last_event_location_delegate1.last_mouse_location());
  EXPECT_EQ(mouse_location,
            last_event_location_delegate2.last_mouse_location());
}

TEST_F(WindowEventDispatcherMusTest, UseDefaultTargeterToFindTarget2) {
  LastEventLocationDelegate last_event_location_delegate1;
  std::unique_ptr<Window> child1(
      CreateTestWindowWithDelegate(&last_event_location_delegate1, 123,
                                   gfx::Rect(10, 10, 100, 100), root_window()));
  LastEventLocationDelegate last_event_location_delegate2;
  std::unique_ptr<Window> child2(
      CreateTestWindowWithDelegate(&last_event_location_delegate2, 124,
                                   gfx::Rect(20, 30, 100, 100), child1.get()));

  const gfx::Point mouse_location(15, 25);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(1, last_event_location_delegate1.mouse_event_count());
  EXPECT_EQ(0, last_event_location_delegate2.mouse_event_count());
  EXPECT_EQ(mouse_location,
            last_event_location_delegate1.last_mouse_location());
  EXPECT_EQ(gfx::Point(), last_event_location_delegate2.last_mouse_location());
}

namespace {

class ExplicitWindowTargeter : public WindowTargeter {
 public:
  explicit ExplicitWindowTargeter(Window* target) : target_(target) {}
  ~ExplicitWindowTargeter() override = default;

  // WindowTargeter:
  ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
                                      ui::Event* event) override {
    return target_;
  }
  ui::EventTarget* FindNextBestTarget(ui::EventTarget* previous_target,
                                      ui::Event* event) override {
    return nullptr;
  }

 private:
  Window* target_;

  DISALLOW_COPY_AND_ASSIGN(ExplicitWindowTargeter);
};

}  // namespace

TEST_F(WindowEventDispatcherMusTest, TargetCaptureWindow) {
  NonClientDelegate w1_delegate;
  NonClientDelegate w2_delegate;
  std::unique_ptr<Window> w1(
      CreateNormalWindow(-1, root_window(), &w1_delegate));
  std::unique_ptr<Window> w2(
      CreateNormalWindow(-1, root_window(), &w2_delegate));
  const gfx::Point w2_origin(10, 11);
  w2->SetBounds(gfx::Rect(w2_origin, gfx::Size(100, 100)));
  NonClientDelegate w2_child_delegate;
  std::unique_ptr<Window> w2_child(
      CreateNormalWindow(-1, w2.get(), &w2_child_delegate));
  w2->SetEventTargeter(
      std::make_unique<ExplicitWindowTargeter>(w2_child.get()));
  w2->SetCapture();
  ASSERT_TRUE(w2->HasCapture());
  const gfx::Point root_location(100, 200);
  const gfx::Point mouse_location(15, 25);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, root_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  ui::Event::DispatcherApi(&mouse).set_target(w1.get());
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(0, w1_delegate.mouse_event_count());
  EXPECT_EQ(1, w2_delegate.mouse_event_count());
  EXPECT_EQ(0, w2_child_delegate.mouse_event_count());
  EXPECT_EQ(mouse_location - w2_origin.OffsetFromOrigin(),
            w2_delegate.mouse_event_location());
}

namespace {

class LocationRecordingEventHandler : public ui::EventHandler {
 public:
  LocationRecordingEventHandler() = default;
  ~LocationRecordingEventHandler() override = default;

  const gfx::Point& event_root_location() const { return event_root_location_; }

  const gfx::Point& env_root_location() const { return env_root_location_; }

  int mouse_event_count() const { return mouse_event_count_; }

  // ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* event) override {
    ++mouse_event_count_;
    event_root_location_ = event->root_location();
    env_root_location_ = Env::GetInstance()->last_mouse_location();
  }

 private:
  int mouse_event_count_ = 0;
  gfx::Point event_root_location_;
  gfx::Point env_root_location_;

  DISALLOW_COPY_AND_ASSIGN(LocationRecordingEventHandler);
};

}  // namespace

TEST_F(WindowEventDispatcherMusTest, RootLocationDoesntChange) {
  std::unique_ptr<Window> window(
      test::CreateTestWindowWithBounds(gfx::Rect(0, 0, 10, 20), root_window()));
  std::unique_ptr<Window> child_window(
      CreateNormalWindow(-1, window.get(), nullptr));

  test::EnvTestHelper().SetAlwaysUseLastMouseLocation(false);

  LocationRecordingEventHandler event_handler;
  child_window->AddPreTargetHandler(&event_handler);

  const gfx::Point mouse_location(1, 2);
  gfx::Point root_location(mouse_location);

  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, root_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  ui::Event::DispatcherApi(&mouse).set_target(child_window.get());
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(1, event_handler.mouse_event_count());

  // The root location during dispatch of the event and Env should match the
  // one that was dispatched.
  EXPECT_EQ(root_location, event_handler.event_root_location());
  EXPECT_EQ(root_location, event_handler.env_root_location());

  child_window->RemovePreTargetHandler(&event_handler);
}

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

  int mouse_event_count() const { return mouse_event_count_; }
  int nested_message_loop_count() const { return nested_message_loop_count_; }
  const gfx::Point& last_mouse_location() const { return last_mouse_location_; }

  // TestWindowDelegate:
  void OnMouseEvent(ui::MouseEvent* event) override {
    ++mouse_event_count_;
    last_mouse_location_ = event->root_location();
    EXPECT_EQ(last_mouse_location_, Env::GetInstance()->last_mouse_location());

    // Start a RunLoop that in turn starts a RunLoop. We have to do this as the
    // first RunLoop doesn't triggering nesting (the MessageLoop isn't running
    // at this point). The second RunLoop (created in InInitialMessageLoop())
    // is considered the first nested loop.
    base::RunLoop run_loop;
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(&NestedLocationDelegate::InInitialMessageLoop,
                                  base::Unretained(this), &run_loop));
    run_loop.Run();
  }

 private:
  void InInitialMessageLoop(base::RunLoop* initial_run_loop) {
    // See comments in OnMouseEvent() for details on which this creates another
    // RunLoop.
    base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(&NestedLocationDelegate::InRunMessageLoop,
                                  base::Unretained(this), &run_loop));
    run_loop.Run();
    initial_run_loop->Quit();
  }

  void InRunMessageLoop(base::RunLoop* run_loop) {
    ++nested_message_loop_count_;
    // nested run loops trigger falling back to using the location from
    // WindowTreeClient, which is 0,0.
    EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());
    run_loop->Quit();
  }

  int mouse_event_count_ = 0;
  // Incremented when the deepest message loop is encountered.
  int nested_message_loop_count_ = 0;
  gfx::Point last_mouse_location_;

  DISALLOW_COPY_AND_ASSIGN(NestedLocationDelegate);
};

TEST_F(WindowEventDispatcherMusTest, EventDispatchTriggersNestedMessageLoop) {
  NestedLocationDelegate last_event_location_delegate;
  std::unique_ptr<Window> window(
      CreateTestWindowWithDelegate(&last_event_location_delegate, 123,
                                   gfx::Rect(0, 0, 10, 20), root_window()));

  // Enable fetching mouse location from mouse.
  test::EnvTestHelper().SetAlwaysUseLastMouseLocation(false);
  EXPECT_EQ(gfx::Point(0, 0),
            window_tree_client_impl()->GetCursorScreenPoint());
  EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());

  // Dispatch an event to |mouse_location|. While dispatching the event
  // Env::last_mouse_location() should return |mouse_location|.
  const gfx::Point mouse_location(1, 2);
  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                       ui::EF_LEFT_MOUSE_BUTTON);
  DispatchEventUsingWindowDispatcher(&mouse);
  EXPECT_EQ(1, last_event_location_delegate.mouse_event_count());
  EXPECT_EQ(1, last_event_location_delegate.nested_message_loop_count());
  EXPECT_EQ(mouse_location, last_event_location_delegate.last_mouse_location());

  // After dispatch the location should fallback to that of the
  // WindowTreeClient, which defaults to 0,0.
  EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());
}

}  // namespace aura
