// Copyright 2016 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 "core/input/PointerEventManager.h"

#include "core/dom/ElementTraversal.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/events/MouseEvent.h"
#include "core/frame/FrameView.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/input/EventHandler.h"
#include "core/input/EventHandlingUtil.h"
#include "core/input/MouseEventManager.h"
#include "core/input/TouchActionUtil.h"
#include "core/layout/HitTestCanvasResult.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "platform/PlatformTouchEvent.h"

namespace blink {

namespace {

size_t toPointerTypeIndex(WebPointerProperties::PointerType t) {
  return static_cast<size_t>(t);
}

const AtomicString& pointerEventNameForTouchPointState(
    PlatformTouchPoint::TouchState state) {
  switch (state) {
    case PlatformTouchPoint::TouchReleased:
      return EventTypeNames::pointerup;
    case PlatformTouchPoint::TouchCancelled:
      return EventTypeNames::pointercancel;
    case PlatformTouchPoint::TouchPressed:
      return EventTypeNames::pointerdown;
    case PlatformTouchPoint::TouchMoved:
      return EventTypeNames::pointermove;
    case PlatformTouchPoint::TouchStationary:
    // Fall through to default
    default:
      NOTREACHED();
      return emptyAtom;
  }
}

bool isInDocument(EventTarget* n) {
  return n && n->toNode() && n->toNode()->isConnected();
}

}  // namespace

PointerEventManager::PointerEventManager(LocalFrame* frame,
                                         MouseEventManager* mouseEventManager)
    : m_frame(frame),
      m_touchEventManager(new TouchEventManager(frame)),
      m_mouseEventManager(mouseEventManager) {
  clear();
}

void PointerEventManager::clear() {
  for (auto& entry : m_preventMouseEventForPointerType)
    entry = false;
  m_touchEventManager->clear();
  m_inCanceledStateForPointerTypeTouch = false;
  m_pointerEventFactory.clear();
  m_touchIdsForCanceledPointerdowns.clear();
  m_nodeUnderPointer.clear();
  m_pointerCaptureTarget.clear();
  m_pendingPointerCaptureTarget.clear();
}

DEFINE_TRACE(PointerEventManager) {
  visitor->trace(m_frame);
  visitor->trace(m_nodeUnderPointer);
  visitor->trace(m_pointerCaptureTarget);
  visitor->trace(m_pendingPointerCaptureTarget);
  visitor->trace(m_touchEventManager);
  visitor->trace(m_mouseEventManager);
}

PointerEventManager::PointerEventBoundaryEventDispatcher::
    PointerEventBoundaryEventDispatcher(
        PointerEventManager* pointerEventManager,
        PointerEvent* pointerEvent)
    : m_pointerEventManager(pointerEventManager),
      m_pointerEvent(pointerEvent) {}

void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOut(
    EventTarget* target,
    EventTarget* relatedTarget) {
  dispatch(target, relatedTarget, EventTypeNames::pointerout, false);
}

void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchOver(
    EventTarget* target,
    EventTarget* relatedTarget) {
  dispatch(target, relatedTarget, EventTypeNames::pointerover, false);
}

void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchLeave(
    EventTarget* target,
    EventTarget* relatedTarget,
    bool checkForListener) {
  dispatch(target, relatedTarget, EventTypeNames::pointerleave,
           checkForListener);
}

void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatchEnter(
    EventTarget* target,
    EventTarget* relatedTarget,
    bool checkForListener) {
  dispatch(target, relatedTarget, EventTypeNames::pointerenter,
           checkForListener);
}

AtomicString
PointerEventManager::PointerEventBoundaryEventDispatcher::getLeaveEvent() {
  return EventTypeNames::pointerleave;
}

AtomicString
PointerEventManager::PointerEventBoundaryEventDispatcher::getEnterEvent() {
  return EventTypeNames::pointerenter;
}

void PointerEventManager::PointerEventBoundaryEventDispatcher::dispatch(
    EventTarget* target,
    EventTarget* relatedTarget,
    const AtomicString& type,
    bool checkForListener) {
  m_pointerEventManager->dispatchPointerEvent(
      target,
      m_pointerEventManager->m_pointerEventFactory.createPointerBoundaryEvent(
          m_pointerEvent, type, relatedTarget),
      checkForListener);
}

WebInputEventResult PointerEventManager::dispatchPointerEvent(
    EventTarget* target,
    PointerEvent* pointerEvent,
    bool checkForListener) {
  if (!target)
    return WebInputEventResult::NotHandled;

  // Set whether node under pointer has received pointerover or not.
  const int pointerId = pointerEvent->pointerId();
  const AtomicString& eventType = pointerEvent->type();
  if ((eventType == EventTypeNames::pointerout ||
       eventType == EventTypeNames::pointerover) &&
      m_nodeUnderPointer.contains(pointerId)) {
    EventTarget* targetUnderPointer = m_nodeUnderPointer.get(pointerId).target;
    if (targetUnderPointer == target) {
      m_nodeUnderPointer.set(
          pointerId,
          EventTargetAttributes(targetUnderPointer,
                                eventType == EventTypeNames::pointerover));
    }
  }

  if (!RuntimeEnabledFeatures::pointerEventEnabled())
    return WebInputEventResult::NotHandled;
  if (!checkForListener || target->hasEventListeners(eventType)) {
    UseCounter::count(m_frame->document(), UseCounter::PointerEventDispatch);
    if (eventType == EventTypeNames::pointerdown)
      UseCounter::count(m_frame->document(),
                        UseCounter::PointerEventDispatchPointerDown);

    DispatchEventResult dispatchResult = target->dispatchEvent(pointerEvent);
    return EventHandlingUtil::toWebInputEventResult(dispatchResult);
  }
  return WebInputEventResult::NotHandled;
}

EventTarget* PointerEventManager::getEffectiveTargetForPointerEvent(
    EventTarget* target,
    int pointerId) {
  if (EventTarget* capturingTarget = getCapturingNode(pointerId))
    return capturingTarget;
  return target;
}

void PointerEventManager::sendMouseAndPointerBoundaryEvents(
    Node* enteredNode,
    const PlatformMouseEvent& mouseEvent) {
  // Mouse event type does not matter as this pointerevent will only be used
  // to create boundary pointer events and its type will be overridden in
  // |sendBoundaryEvents| function.
  PointerEvent* dummyPointerEvent = m_pointerEventFactory.create(
      EventTypeNames::mousedown, mouseEvent, m_frame->document()->domWindow());

  // TODO(crbug/545647): This state should reset with pointercancel too.
  // This function also gets called for compat mouse events of touch at this
  // stage. So if the event is not frame boundary transition it is only a
  // compatibility mouse event and we do not need to change pointer event
  // behavior regarding preventMouseEvent state in that case.
  if (dummyPointerEvent->buttons() == 0 && dummyPointerEvent->isPrimary()) {
    m_preventMouseEventForPointerType[toPointerTypeIndex(
        mouseEvent.pointerProperties().pointerType)] = false;
  }

  processCaptureAndPositionOfPointerEvent(dummyPointerEvent, enteredNode,
                                          mouseEvent, true);
}

void PointerEventManager::sendBoundaryEvents(EventTarget* exitedTarget,
                                             EventTarget* enteredTarget,
                                             PointerEvent* pointerEvent) {
  if (RuntimeEnabledFeatures::pointerEventV1SpecCapturingEnabled()) {
    if (exitedTarget == enteredTarget)
      return;
    if (EventTarget* capturingTarget =
            getCapturingNode(pointerEvent->pointerId())) {
      if (capturingTarget == exitedTarget)
        enteredTarget = nullptr;
      else if (capturingTarget == enteredTarget)
        exitedTarget = nullptr;
      else
        return;
    }
  }
  PointerEventBoundaryEventDispatcher boundaryEventDispatcher(this,
                                                              pointerEvent);
  boundaryEventDispatcher.sendBoundaryEvents(exitedTarget, enteredTarget);
}

void PointerEventManager::setNodeUnderPointer(PointerEvent* pointerEvent,
                                              EventTarget* target) {
  if (m_nodeUnderPointer.contains(pointerEvent->pointerId())) {
    EventTargetAttributes node =
        m_nodeUnderPointer.get(pointerEvent->pointerId());
    if (!target) {
      m_nodeUnderPointer.remove(pointerEvent->pointerId());
    } else if (target !=
               m_nodeUnderPointer.get(pointerEvent->pointerId()).target) {
      m_nodeUnderPointer.set(pointerEvent->pointerId(),
                             EventTargetAttributes(target, false));
    }
    sendBoundaryEvents(node.target, target, pointerEvent);
  } else if (target) {
    m_nodeUnderPointer.add(pointerEvent->pointerId(),
                           EventTargetAttributes(target, false));
    sendBoundaryEvents(nullptr, target, pointerEvent);
  }
}

void PointerEventManager::blockTouchPointers() {
  if (m_inCanceledStateForPointerTypeTouch)
    return;
  m_inCanceledStateForPointerTypeTouch = true;

  Vector<int> touchPointerIds = m_pointerEventFactory.getPointerIdsOfType(
      WebPointerProperties::PointerType::Touch);

  for (int pointerId : touchPointerIds) {
    PointerEvent* pointerEvent = m_pointerEventFactory.createPointerCancelEvent(
        pointerId, WebPointerProperties::PointerType::Touch);

    DCHECK(m_nodeUnderPointer.contains(pointerId));
    EventTarget* target = m_nodeUnderPointer.get(pointerId).target;

    processCaptureAndPositionOfPointerEvent(pointerEvent, target);

    // TODO(nzolghadr): This event follows implicit TE capture. The actual
    // target would depend on PE capturing. Perhaps need to split TE/PE event
    // path upstream?  crbug.com/579553.
    dispatchPointerEvent(
        getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()),
        pointerEvent);

    releasePointerCapture(pointerEvent->pointerId());

    // Sending the leave/out events and lostpointercapture
    // because the next touch event will have a different id. So delayed
    // sending of lostpointercapture won't work here.
    processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr);

    removePointer(pointerEvent);
  }
}

void PointerEventManager::unblockTouchPointers() {
  m_inCanceledStateForPointerTypeTouch = false;
}

WebInputEventResult PointerEventManager::handleTouchEvents(
    const PlatformTouchEvent& event) {
  if (event.type() == PlatformEvent::TouchScrollStarted) {
    blockTouchPointers();
    m_touchEventManager->setTouchScrollStarted();
    return WebInputEventResult::HandledSystem;
  }

  bool newTouchSequence = true;
  for (const auto& touchPoint : event.touchPoints()) {
    if (touchPoint.state() != PlatformTouchPoint::TouchPressed) {
      newTouchSequence = false;
      break;
    }
  }
  if (newTouchSequence)
    unblockTouchPointers();
  HeapVector<TouchEventManager::TouchInfo> touchInfos;

  dispatchTouchPointerEvents(event, touchInfos);

  return m_touchEventManager->handleTouchEvent(event, touchInfos);
}

void PointerEventManager::dispatchTouchPointerEvents(
    const PlatformTouchEvent& event,
    HeapVector<TouchEventManager::TouchInfo>& touchInfos) {
  // Iterate through the touch points, sending PointerEvents to the targets as
  // required.
  for (const auto& touchPoint : event.touchPoints()) {
    TouchEventManager::TouchInfo touchInfo;
    touchInfo.point = touchPoint;

    int pointerId =
        m_pointerEventFactory.getPointerEventId(touchPoint.pointerProperties());
    // Do the hit test either when the touch first starts or when the touch
    // is not captured. |m_pendingPointerCaptureTarget| indicates the target
    // that will be capturing this event. |m_pointerCaptureTarget| may not
    // have this target yet since the processing of that will be done right
    // before firing the event.
    if (RuntimeEnabledFeatures::pointerEventV1SpecCapturingEnabled() ||
        touchInfo.point.state() == PlatformTouchPoint::TouchPressed ||
        !m_pendingPointerCaptureTarget.contains(pointerId)) {
      HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent |
                                                   HitTestRequest::ReadOnly |
                                                   HitTestRequest::Active;
      LayoutPoint pagePoint = roundedLayoutPoint(
          m_frame->view()->rootFrameToContents(touchInfo.point.pos()));
      HitTestResult hitTestTesult =
          m_frame->eventHandler().hitTestResultAtPoint(pagePoint, hitType);
      Node* node = hitTestTesult.innerNode();
      if (node) {
        touchInfo.targetFrame = node->document().frame();
        if (isHTMLCanvasElement(node)) {
          HitTestCanvasResult* hitTestCanvasResult =
              toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists(
                  hitTestTesult.pointInInnerNodeFrame());
          if (hitTestCanvasResult->getControl())
            node = hitTestCanvasResult->getControl();
          touchInfo.region = hitTestCanvasResult->getId();
        }
        // TODO(crbug.com/612456): We need to investigate whether pointer
        // events should go to text nodes or not. If so we need to
        // update the mouse code as well. Also this logic looks similar
        // to the one in TouchEventManager. We should be able to
        // refactor it better after this investigation.
        if (node->isTextNode())
          node = FlatTreeTraversal::parent(*node);
        touchInfo.touchNode = node;
      }
    } else {
      // Set the target of pointer event to the captured node as this
      // pointer is captured otherwise it would have gone to the if block
      // and perform a hit-test.
      touchInfo.touchNode =
          m_pendingPointerCaptureTarget.get(pointerId)->toNode();
      touchInfo.targetFrame = touchInfo.touchNode->document().frame();
    }

    // Do not send pointer events for stationary touches or null targetFrame
    if (touchInfo.touchNode && touchInfo.targetFrame &&
        touchPoint.state() != PlatformTouchPoint::TouchStationary &&
        !m_inCanceledStateForPointerTypeTouch) {
      FloatPoint pagePoint = touchInfo.targetFrame->view()->rootFrameToContents(
          touchInfo.point.pos());
      float scaleFactor = 1.0f / touchInfo.targetFrame->pageZoomFactor();
      FloatPoint scrollPosition =
          touchInfo.targetFrame->view()->scrollPosition();
      FloatPoint framePoint = pagePoint.scaledBy(scaleFactor);
      framePoint.moveBy(scrollPosition.scaledBy(-scaleFactor));
      PointerEvent* pointerEvent = m_pointerEventFactory.create(
          pointerEventNameForTouchPointState(touchPoint.state()), touchPoint,
          event.getModifiers(), touchPoint.radius().scaledBy(scaleFactor),
          framePoint,
          touchInfo.touchNode ? touchInfo.touchNode->document().domWindow()
                              : nullptr);

      WebInputEventResult result =
          sendTouchPointerEvent(touchInfo.touchNode, pointerEvent);

      // If a pointerdown has been canceled, queue the unique id to allow
      // suppressing mouse events from gesture events. For mouse events
      // fired from GestureTap & GestureLongPress (which are triggered by
      // single touches only), it is enough to queue the ids only for
      // primary pointers.
      // TODO(mustaq): What about other cases (e.g. GestureTwoFingerTap)?
      if (result != WebInputEventResult::NotHandled &&
          pointerEvent->type() == EventTypeNames::pointerdown &&
          pointerEvent->isPrimary()) {
        m_touchIdsForCanceledPointerdowns.append(event.uniqueTouchEventId());
      }
    }

    touchInfos.append(touchInfo);
  }
}

WebInputEventResult PointerEventManager::sendTouchPointerEvent(
    EventTarget* target,
    PointerEvent* pointerEvent) {
  if (m_inCanceledStateForPointerTypeTouch)
    return WebInputEventResult::NotHandled;

  processCaptureAndPositionOfPointerEvent(pointerEvent, target);

  // Setting the implicit capture for touch
  if (!RuntimeEnabledFeatures::pointerEventV1SpecCapturingEnabled() &&
      pointerEvent->type() == EventTypeNames::pointerdown)
    setPointerCapture(pointerEvent->pointerId(), target);

  WebInputEventResult result = dispatchPointerEvent(
      getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()),
      pointerEvent);

  if (pointerEvent->type() == EventTypeNames::pointerup ||
      pointerEvent->type() == EventTypeNames::pointercancel) {
    releasePointerCapture(pointerEvent->pointerId());

    // Sending the leave/out events and lostpointercapture because the next
    // touch event will have a different id.
    processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr);

    removePointer(pointerEvent);
  }

  return result;
}

WebInputEventResult PointerEventManager::sendMousePointerEvent(
    Node* target,
    const AtomicString& mouseEventType,
    const PlatformMouseEvent& mouseEvent) {
  PointerEvent* pointerEvent = m_pointerEventFactory.create(
      mouseEventType, mouseEvent, m_frame->document()->domWindow());

  // This is for when the mouse is released outside of the page.
  if (pointerEvent->type() == EventTypeNames::pointermove &&
      !pointerEvent->buttons()) {
    releasePointerCapture(pointerEvent->pointerId());
    // Send got/lostpointercapture rightaway if necessary.
    processPendingPointerCapture(pointerEvent);

    if (pointerEvent->isPrimary()) {
      m_preventMouseEventForPointerType[toPointerTypeIndex(
          mouseEvent.pointerProperties().pointerType)] = false;
    }
  }

  EventTarget* pointerEventTarget = processCaptureAndPositionOfPointerEvent(
      pointerEvent, target, mouseEvent, true);

  EventTarget* effectiveTarget = getEffectiveTargetForPointerEvent(
      pointerEventTarget, pointerEvent->pointerId());

  WebInputEventResult result =
      dispatchPointerEvent(effectiveTarget, pointerEvent);

  if (result != WebInputEventResult::NotHandled &&
      pointerEvent->type() == EventTypeNames::pointerdown &&
      pointerEvent->isPrimary()) {
    m_preventMouseEventForPointerType[toPointerTypeIndex(
        mouseEvent.pointerProperties().pointerType)] = true;
  }

  if (pointerEvent->isPrimary() &&
      !m_preventMouseEventForPointerType[toPointerTypeIndex(
          mouseEvent.pointerProperties().pointerType)]) {
    EventTarget* mouseTarget = effectiveTarget;
    // Event path could be null if pointer event is not dispatched and
    // that happens for example when pointer event feature is not enabled.
    if (!isInDocument(mouseTarget) && pointerEvent->hasEventPath()) {
      for (size_t i = 0; i < pointerEvent->eventPath().size(); i++) {
        if (isInDocument(pointerEvent->eventPath()[i].node())) {
          mouseTarget = pointerEvent->eventPath()[i].node();
          break;
        }
      }
    }
    result = EventHandlingUtil::mergeEventResult(
        result, m_mouseEventManager->dispatchMouseEvent(
                    mouseTarget, mouseEventType, mouseEvent, nullptr));
  }

  if (pointerEvent->type() == EventTypeNames::pointerup ||
      pointerEvent->type() == EventTypeNames::pointercancel) {
    releasePointerCapture(pointerEvent->pointerId());
    // Send got/lostpointercapture rightaway if necessary.
    processPendingPointerCapture(pointerEvent);

    if (pointerEvent->isPrimary()) {
      m_preventMouseEventForPointerType[toPointerTypeIndex(
          mouseEvent.pointerProperties().pointerType)] = false;
    }
  }

  return result;
}

bool PointerEventManager::getPointerCaptureState(
    int pointerId,
    EventTarget** pointerCaptureTarget,
    EventTarget** pendingPointerCaptureTarget) {
  PointerCapturingMap::const_iterator it;

  it = m_pointerCaptureTarget.find(pointerId);
  EventTarget* pointerCaptureTargetTemp =
      (it != m_pointerCaptureTarget.end()) ? it->value : nullptr;
  it = m_pendingPointerCaptureTarget.find(pointerId);
  EventTarget* pendingPointercaptureTargetTemp =
      (it != m_pendingPointerCaptureTarget.end()) ? it->value : nullptr;

  if (pointerCaptureTarget)
    *pointerCaptureTarget = pointerCaptureTargetTemp;
  if (pendingPointerCaptureTarget)
    *pendingPointerCaptureTarget = pendingPointercaptureTargetTemp;

  return pointerCaptureTargetTemp != pendingPointercaptureTargetTemp;
}

EventTarget* PointerEventManager::processCaptureAndPositionOfPointerEvent(
    PointerEvent* pointerEvent,
    EventTarget* hitTestTarget,
    const PlatformMouseEvent& mouseEvent,
    bool sendMouseEvent) {
  processPendingPointerCapture(pointerEvent);

  if (!RuntimeEnabledFeatures::pointerEventV1SpecCapturingEnabled()) {
    PointerCapturingMap::const_iterator it =
        m_pointerCaptureTarget.find(pointerEvent->pointerId());
    if (EventTarget* pointercaptureTarget =
            (it != m_pointerCaptureTarget.end()) ? it->value : nullptr)
      hitTestTarget = pointercaptureTarget;
  }

  setNodeUnderPointer(pointerEvent, hitTestTarget);
  if (sendMouseEvent) {
    m_mouseEventManager->setNodeUnderMouse(
        hitTestTarget ? hitTestTarget->toNode() : nullptr, mouseEvent);
  }
  return hitTestTarget;
}

void PointerEventManager::processPendingPointerCapture(
    PointerEvent* pointerEvent) {
  EventTarget* pointerCaptureTarget;
  EventTarget* pendingPointerCaptureTarget;
  const int pointerId = pointerEvent->pointerId();
  const bool isCaptureChanged = getPointerCaptureState(
      pointerId, &pointerCaptureTarget, &pendingPointerCaptureTarget);

  if (!isCaptureChanged)
    return;

  // We have to check whether the pointerCaptureTarget is null or not because
  // we are checking whether it is still connected to its document or not.
  if (pointerCaptureTarget) {
    // Re-target lostpointercapture to the document when the element is
    // no longer participating in the tree.
    EventTarget* target = pointerCaptureTarget;
    if (target->toNode() && !target->toNode()->isConnected()) {
      target = target->toNode()->ownerDocument();
    }
    dispatchPointerEvent(target,
                         m_pointerEventFactory.createPointerCaptureEvent(
                             pointerEvent, EventTypeNames::lostpointercapture));
  }
  // Note that If pendingPointerCaptureTarget is null dispatchPointerEvent
  // automatically does nothing.
  dispatchPointerEvent(pendingPointerCaptureTarget,
                       m_pointerEventFactory.createPointerCaptureEvent(
                           pointerEvent, EventTypeNames::gotpointercapture));

  if (pendingPointerCaptureTarget)
    m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
  else
    m_pointerCaptureTarget.remove(pointerId);
}

void PointerEventManager::removeTargetFromPointerCapturingMapping(
    PointerCapturingMap& map,
    const EventTarget* target) {
  // We could have kept a reverse mapping to make this deletion possibly
  // faster but it adds some code complication which might not be worth of
  // the performance improvement considering there might not be a lot of
  // active pointer or pointer captures at the same time.
  PointerCapturingMap tmp = map;
  for (PointerCapturingMap::iterator it = tmp.begin(); it != tmp.end(); ++it) {
    if (it->value == target)
      map.remove(it->key);
  }
}

EventTarget* PointerEventManager::getCapturingNode(int pointerId) {
  if (m_pointerCaptureTarget.contains(pointerId))
    return m_pointerCaptureTarget.get(pointerId);
  return nullptr;
}

void PointerEventManager::removePointer(PointerEvent* pointerEvent) {
  int pointerId = pointerEvent->pointerId();
  if (m_pointerEventFactory.remove(pointerId)) {
    m_pendingPointerCaptureTarget.remove(pointerId);
    m_pointerCaptureTarget.remove(pointerId);
    m_nodeUnderPointer.remove(pointerId);
  }
}

void PointerEventManager::elementRemoved(EventTarget* target) {
  removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget,
                                          target);
}

void PointerEventManager::setPointerCapture(int pointerId,
                                            EventTarget* target) {
  UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
  if (m_pointerEventFactory.isActiveButtonsState(pointerId))
    m_pendingPointerCaptureTarget.set(pointerId, target);
}

void PointerEventManager::releasePointerCapture(int pointerId,
                                                EventTarget* target) {
  // Only the element that is going to get the next pointer event can release
  // the capture. Note that this might be different from
  // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element
  // that had the capture until now and has been receiving the pointerevents
  // but |m_pendingPointerCaptureTarget| indicated the element that gets the
  // very next pointer event. They will be the same if there was no change in
  // capturing of a particular |pointerId|. See crbug.com/614481.
  if (m_pendingPointerCaptureTarget.get(pointerId) == target)
    releasePointerCapture(pointerId);
}

bool PointerEventManager::hasPointerCapture(int pointerId,
                                            const EventTarget* target) const {
  return m_pendingPointerCaptureTarget.get(pointerId) == target;
}

bool PointerEventManager::hasProcessedPointerCapture(
    int pointerId,
    const EventTarget* target) const {
  return m_pointerCaptureTarget.get(pointerId) == target;
}

void PointerEventManager::releasePointerCapture(int pointerId) {
  m_pendingPointerCaptureTarget.remove(pointerId);
}

bool PointerEventManager::isActive(const int pointerId) const {
  return m_pointerEventFactory.isActive(pointerId);
}

bool PointerEventManager::isAnyTouchActive() const {
  return m_touchEventManager->isAnyTouchActive();
}

bool PointerEventManager::primaryPointerdownCanceled(
    uint32_t uniqueTouchEventId) {
  // It's safe to assume that uniqueTouchEventIds won't wrap back to 0 from
  // 2^32-1 (>4.2 billion): even with a generous 100 unique ids per touch
  // sequence & one sequence per 10 second, it takes 13+ years to wrap back.
  while (!m_touchIdsForCanceledPointerdowns.isEmpty()) {
    uint32_t firstId = m_touchIdsForCanceledPointerdowns.first();
    if (firstId > uniqueTouchEventId)
      return false;
    m_touchIdsForCanceledPointerdowns.takeFirst();
    if (firstId == uniqueTouchEventId)
      return true;
  }
  return false;
}

EventTarget* PointerEventManager::getMouseCapturingNode() {
  return getCapturingNode(PointerEventFactory::s_mouseId);
}

}  // namespace blink
