// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/window_targeter.h"

#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event_target.h"

namespace aura {

namespace {

bool IsLocatedEvent(const ui::Event& event) {
  return event.IsMouseEvent() || event.IsTouchEvent() ||
         event.IsScrollEvent() || event.IsGestureEvent();
}

}  // namespace

WindowTargeter::WindowTargeter() {}
WindowTargeter::~WindowTargeter() {}

ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
                                                    ui::Event* event) {
  Window* window = static_cast<Window*>(root);
  Window* target = event->IsKeyEvent() ?
      FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
      static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
  if (target && !window->parent() && !window->Contains(target)) {
    // |window| is the root window, but |target| is not a descendent of
    // |window|. So do not allow dispatching from here. Instead, dispatch the
    // event through the WindowEventDispatcher that owns |target|.
    aura::Window* new_root = target->GetRootWindow();
    if (IsLocatedEvent(*event)) {
      // The event has been transformed to be in |target|'s coordinate system.
      // But dispatching the event through the EventProcessor requires the event
      // to be in the host's coordinate system. So, convert the event to be in
      // the root's coordinate space, and then to the host's coordinate space by
      // applying the host's transform.
      ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
      located_event->ConvertLocationToTarget(target, new_root);
      located_event->UpdateForRootTransform(
          new_root->GetHost()->GetRootTransform());
    }
    ignore_result(
        new_root->GetHost()->event_processor()->OnEventFromSource(event));

    target = NULL;
  }
  return target;
}

bool WindowTargeter::SubtreeCanAcceptEvent(
    ui::EventTarget* target,
    const ui::LocatedEvent& event) const {
  aura::Window* window = static_cast<aura::Window*>(target);
  if (!window->IsVisible())
    return false;
  if (window->ignore_events())
    return false;
  client::EventClient* client = client::GetEventClient(window->GetRootWindow());
  if (client && !client->CanProcessEventsWithinSubtree(window))
    return false;

  Window* parent = window->parent();
  if (parent && parent->delegate_ && !parent->delegate_->
      ShouldDescendIntoChildForEventHandling(window, event.location())) {
    return false;
  }
  return true;
}

bool WindowTargeter::EventLocationInsideBounds(
    ui::EventTarget* target,
    const ui::LocatedEvent& event) const {
  aura::Window* window = static_cast<aura::Window*>(target);
  gfx::Point point = event.location();
  if (window->parent())
    aura::Window::ConvertPointToTarget(window->parent(), window, &point);
  return gfx::Rect(window->bounds().size()).Contains(point);
}

ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
    ui::EventTarget* root,
    ui::LocatedEvent* event) {
  Window* window = static_cast<Window*>(root);
  if (!window->parent()) {
    Window* target = FindTargetInRootWindow(window, *event);
    if (target) {
      window->ConvertEventToTarget(target, event);
      return target;
    }
  }
  return EventTargeter::FindTargetForLocatedEvent(root, event);
}

Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
                                              const ui::KeyEvent& key) {
  Window* root_window = window->GetRootWindow();
  client::FocusClient* focus_client = client::GetFocusClient(root_window);
  Window* focused_window = focus_client->GetFocusedWindow();
  if (!focused_window)
    return window;

  client::EventClient* event_client = client::GetEventClient(root_window);
  if (event_client &&
      !event_client->CanProcessEventsWithinSubtree(focused_window)) {
    focus_client->FocusWindow(NULL);
    return NULL;
  }
  return focused_window ? focused_window : window;
}

Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
                                               const ui::LocatedEvent& event) {
  DCHECK_EQ(root_window, root_window->GetRootWindow());

  // Mouse events should be dispatched to the window that processed the
  // mouse-press events (if any).
  if (event.IsScrollEvent() || event.IsMouseEvent()) {
    WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
    if (dispatcher->mouse_pressed_handler())
      return dispatcher->mouse_pressed_handler();
  }

  // All events should be directed towards the capture window (if any).
  Window* capture_window = client::GetCaptureWindow(root_window);
  if (capture_window)
    return capture_window;

  if (event.IsTouchEvent()) {
    // Query the gesture-recognizer to find targets for touch events.
    const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
    ui::GestureConsumer* consumer =
        ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
    if (consumer)
      return static_cast<Window*>(consumer);
    consumer =
        ui::GestureRecognizer::Get()->GetTargetForLocation(
            event.location(), touch.source_device_id());
    if (consumer)
      return static_cast<Window*>(consumer);

    // If the initial touch is outside the root window, target the root.
    if (!root_window->bounds().Contains(event.location()))
      return root_window;
  }

  return NULL;
}

}  // namespace aura
