blob: faedf8b6931405fb57d5f8b20217357992ac5f15 [file] [log] [blame]
// 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.
#ifndef PointerEventManager_h
#define PointerEventManager_h
#include "core/CoreExport.h"
#include "core/events/PointerEvent.h"
#include "core/events/PointerEventFactory.h"
#include "core/input/BoundaryEventDispatcher.h"
#include "core/input/TouchEventManager.h"
#include "public/platform/WebInputEventResult.h"
#include "public/platform/WebPointerProperties.h"
#include "wtf/Allocator.h"
#include "wtf/HashMap.h"
namespace blink {
class LocalFrame;
class MouseEventManager;
// This class takes care of dispatching all pointer events and keeps track of
// properties of active pointer events.
class CORE_EXPORT PointerEventManager
: public GarbageCollectedFinalized<PointerEventManager> {
WTF_MAKE_NONCOPYABLE(PointerEventManager);
public:
PointerEventManager(LocalFrame*, MouseEventManager*);
DECLARE_TRACE();
// Sends the mouse pointer events and the boundary events
// that it may cause. It also sends the compat mouse events
// and sets the newNodeUnderMouse if the capturing is set
// in this function.
WebInputEventResult sendMousePointerEvent(Node* target,
const AtomicString& type,
const PlatformMouseEvent&);
WebInputEventResult handleTouchEvents(const PlatformTouchEvent&);
// Sends boundary events pointerout/leave/over/enter and
// mouseout/leave/over/enter to the corresponding targets.
// inside the document. This functions handles the cases that pointer is
// leaving a frame. Note that normal mouse events (e.g. mousemove/down/up)
// and their corresponding boundary events will be handled altogether by
// sendMousePointerEvent function.
void sendMouseAndPointerBoundaryEvents(Node* enteredNode,
const PlatformMouseEvent&);
// Resets the internal state of this object.
void clear();
void elementRemoved(EventTarget*);
void setPointerCapture(int, EventTarget*);
void releasePointerCapture(int, EventTarget*);
// See Element::hasPointerCapture(int).
bool hasPointerCapture(int, const EventTarget*) const;
// See Element::hasProcessedPointerCapture(int).
bool hasProcessedPointerCapture(int, const EventTarget*) const;
bool isActive(const int) const;
// Returns whether there is any touch on the screen.
bool isAnyTouchActive() const;
// TODO(crbug.com/625843): This can be hidden when mouse refactoring in
// EventHandler is done.
EventTarget* getMouseCapturingNode();
// Returns true if the primary pointerdown corresponding to the given
// |uniqueTouchEventId| was canceled. Also drops stale ids from
// |m_touchIdsForCanceledPointerdowns|.
bool primaryPointerdownCanceled(uint32_t uniqueTouchEventId);
private:
typedef HeapHashMap<int,
Member<EventTarget>,
WTF::IntHash<int>,
WTF::UnsignedWithZeroKeyHashTraits<int>>
PointerCapturingMap;
class EventTargetAttributes {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
DEFINE_INLINE_TRACE() { visitor->trace(target); }
Member<EventTarget> target;
bool hasRecievedOverEvent;
EventTargetAttributes() : target(nullptr), hasRecievedOverEvent(false) {}
EventTargetAttributes(EventTarget* target, bool hasRecievedOverEvent)
: target(target), hasRecievedOverEvent(hasRecievedOverEvent) {}
};
class PointerEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
WTF_MAKE_NONCOPYABLE(PointerEventBoundaryEventDispatcher);
public:
PointerEventBoundaryEventDispatcher(PointerEventManager*, PointerEvent*);
protected:
void dispatchOut(EventTarget*, EventTarget* relatedTarget) override;
void dispatchOver(EventTarget*, EventTarget* relatedTarget) override;
void dispatchLeave(EventTarget*,
EventTarget* relatedTarget,
bool checkForListener) override;
void dispatchEnter(EventTarget*,
EventTarget* relatedTarget,
bool checkForListener) override;
AtomicString getLeaveEvent() override;
AtomicString getEnterEvent() override;
private:
void dispatch(EventTarget*,
EventTarget* relatedTarget,
const AtomicString&,
bool checkForListener);
Member<PointerEventManager> m_pointerEventManager;
Member<PointerEvent> m_pointerEvent;
};
// Inhibits firing of touch-type PointerEvents until unblocked by
// unblockTouchPointers(). Also sends pointercancels for existing touch-type
// PointerEvents. See:
// www.w3.org/TR/pointerevents/#declaring-candidate-regions-for-default-touch-behaviors
void blockTouchPointers();
// Enables firing of touch-type PointerEvents after they were inhibited by
// blockTouchPointers().
void unblockTouchPointers();
// Sends touch pointer events and sets consumed bits in TouchInfo array
// based on the return value of pointer event handlers.
void dispatchTouchPointerEvents(const PlatformTouchEvent&,
HeapVector<TouchEventManager::TouchInfo>&);
// Returns whether the event is consumed or not.
WebInputEventResult sendTouchPointerEvent(EventTarget*, PointerEvent*);
void sendBoundaryEvents(EventTarget* exitedTarget,
EventTarget* enteredTarget,
PointerEvent*);
void setNodeUnderPointer(PointerEvent*, EventTarget*);
// Processes the assignment of |m_pointerCaptureTarget| from
// |m_pendingPointerCaptureTarget| and sends the got/lostpointercapture
// events, as per the spec:
// https://w3c.github.io/pointerevents/#process-pending-pointer-capture
void processPendingPointerCapture(PointerEvent*);
// Processes the capture state of a pointer, updates node under
// pointer, and sends corresponding boundary events for pointer if
// setPointerPosition is true. It also sends corresponding boundary events
// for mouse if sendMouseEvent is true.
// Returns the target that the pointer event is supposed to be fired at.
EventTarget* processCaptureAndPositionOfPointerEvent(
PointerEvent*,
EventTarget* hitTestTarget,
const PlatformMouseEvent& = PlatformMouseEvent(),
bool sendMouseEvent = false);
void removeTargetFromPointerCapturingMapping(PointerCapturingMap&,
const EventTarget*);
EventTarget* getEffectiveTargetForPointerEvent(EventTarget*, int);
EventTarget* getCapturingNode(int);
void removePointer(PointerEvent*);
WebInputEventResult dispatchPointerEvent(EventTarget*,
PointerEvent*,
bool checkForListener = false);
void releasePointerCapture(int);
// Returns true if capture target and pending capture target were different.
bool getPointerCaptureState(int pointerId,
EventTarget** pointerCaptureTarget,
EventTarget** pendingPointerCaptureTarget);
// NOTE: If adding a new field to this class please ensure that it is
// cleared in |PointerEventManager::clear()|.
const Member<LocalFrame> m_frame;
// Prevents firing mousedown, mousemove & mouseup in-between a canceled
// pointerdown and next pointerup/pointercancel.
// See "PREVENT MOUSE EVENT flag" in the spec:
// https://w3c.github.io/pointerevents/#compatibility-mapping-with-mouse-events
bool m_preventMouseEventForPointerType
[static_cast<size_t>(WebPointerProperties::PointerType::LastEntry) + 1];
// Set upon sending a pointercancel for touch, prevents PE dispatches for
// touches until all touch-points become inactive.
bool m_inCanceledStateForPointerTypeTouch;
Deque<uint32_t> m_touchIdsForCanceledPointerdowns;
// Note that this map keeps track of node under pointer with id=1 as well
// which might be different than m_nodeUnderMouse in EventHandler. That one
// keeps track of any compatibility mouse event positions but this map for
// the pointer with id=1 is only taking care of true mouse related events.
using NodeUnderPointerMap =
HeapHashMap<int,
EventTargetAttributes,
WTF::IntHash<int>,
WTF::UnsignedWithZeroKeyHashTraits<int>>;
NodeUnderPointerMap m_nodeUnderPointer;
PointerCapturingMap m_pointerCaptureTarget;
PointerCapturingMap m_pendingPointerCaptureTarget;
PointerEventFactory m_pointerEventFactory;
Member<TouchEventManager> m_touchEventManager;
Member<MouseEventManager> m_mouseEventManager;
};
} // namespace blink
#endif // PointerEventManager_h