blob: 536d337cd69e10cd5c9efc459f99b472877b2e77 [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 MouseEventManager_h
#define MouseEventManager_h
#include "core/CoreExport.h"
#include "core/input/BoundaryEventDispatcher.h"
#include "core/page/DragActions.h"
#include "core/page/EventWithHitTestResults.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/Timer.h"
#include "public/platform/WebInputEventResult.h"
#include "wtf/Allocator.h"
namespace blink {
class DragState;
class DataTransfer;
class Element;
class FloatQuad;
class HitTestResult;
class InputDeviceCapabilities;
class LocalFrame;
class ScrollManager;
enum class DragInitiator;
// This class takes care of dispatching all mouse events and keeps track of
// positions and states of mouse.
class CORE_EXPORT MouseEventManager
: public GarbageCollectedFinalized<MouseEventManager> {
WTF_MAKE_NONCOPYABLE(MouseEventManager);
public:
MouseEventManager(LocalFrame*, ScrollManager*);
DECLARE_TRACE();
WebInputEventResult dispatchMouseEvent(EventTarget*,
const AtomicString&,
const PlatformMouseEvent&,
EventTarget* relatedTarget,
bool checkForListener = false);
WebInputEventResult setMousePositionAndDispatchMouseEvent(
Node* targetNode,
const AtomicString& eventType,
const PlatformMouseEvent&);
WebInputEventResult dispatchMouseClickIfNeeded(
const MouseEventWithHitTestResults&);
WebInputEventResult dispatchDragSrcEvent(const AtomicString& eventType,
const PlatformMouseEvent&);
WebInputEventResult dispatchDragEvent(const AtomicString& eventType,
Node* target,
const PlatformMouseEvent&,
DataTransfer*);
// Resets the internal state of this object.
void clear();
void sendBoundaryEvents(EventTarget* exitedTarget,
EventTarget* enteredTarget,
const PlatformMouseEvent& mousePlatformEvent);
void setNodeUnderMouse(Node*, const PlatformMouseEvent&);
WebInputEventResult handleMouseFocus(
const HitTestResult&,
InputDeviceCapabilities* sourceCapabilities);
void fakeMouseMoveEventTimerFired(TimerBase*);
void cancelFakeMouseMoveEvent();
void dispatchFakeMouseMoveEventSoon();
void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);
void setLastKnownMousePosition(const PlatformMouseEvent&);
bool handleDragDropIfPossible(const GestureEventWithHitTestResults&);
WebInputEventResult handleMouseDraggedEvent(
const MouseEventWithHitTestResults&);
WebInputEventResult handleMousePressEvent(
const MouseEventWithHitTestResults&);
WebInputEventResult handleMouseReleaseEvent(
const MouseEventWithHitTestResults&);
void nodeWillBeRemoved(Node& nodeToBeRemoved);
static DragState& dragState();
void focusDocumentView();
// Resets the state that indicates the next events could cause a drag. It is
// called when we realize the next events should not cause drag based on the
// drag heuristics.
void clearDragHeuristicState();
void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation);
void updateSelectionForMouseDrag();
void handleMousePressEventUpdateStates(const PlatformMouseEvent&);
// Returns whether pan is handled and resets the state on release.
bool handleSvgPanIfNeeded(bool isReleaseEvent);
void invalidateClick();
// TODO: These functions ideally should be private but the code needs more
// refactoring to be able to remove the dependency from EventHandler.
Node* getNodeUnderMouse();
bool isMousePositionUnknown();
IntPoint lastKnownMousePosition();
bool mousePressed();
void setMousePressed(bool);
bool capturesDragging() const;
void setCapturesDragging(bool);
void setMouseDownMayStartAutoscroll() {
m_mouseDownMayStartAutoscroll = true;
}
Node* mousePressNode();
void setMousePressNode(Node*);
void setClickNode(Node*);
void setClickCount(int);
bool mouseDownMayStartDrag();
private:
class MouseEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
WTF_MAKE_NONCOPYABLE(MouseEventBoundaryEventDispatcher);
public:
MouseEventBoundaryEventDispatcher(MouseEventManager*,
const PlatformMouseEvent*,
EventTarget* exitedTarget);
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&,
const PlatformMouseEvent&,
bool checkForListener);
Member<MouseEventManager> m_mouseEventManager;
const PlatformMouseEvent* m_platformMouseEvent;
Member<EventTarget> m_exitedTarget;
};
// If the given element is a shadow host and its root has delegatesFocus=false
// flag, slide focus to its inner element. Returns true if the resulting focus
// is different from the given element.
bool slideFocusOnShadowHostIfNecessary(const Element&);
bool dragHysteresisExceeded(const IntPoint&) const;
bool handleDrag(const MouseEventWithHitTestResults&, DragInitiator);
bool tryStartDrag(const MouseEventWithHitTestResults&);
void clearDragDataTransfer();
DataTransfer* createDraggingDataTransfer() const;
// NOTE: If adding a new field to this class please ensure that it is
// cleared in |MouseEventManager::clear()|.
const Member<LocalFrame> m_frame;
Member<ScrollManager> m_scrollManager;
// The effective position of the mouse pointer.
// See
// https://w3c.github.io/pointerevents/#dfn-tracking-the-effective-position-of-the-legacy-mouse-pointer.
Member<Node> m_nodeUnderMouse;
// The last mouse movement position this frame has seen in root frame
// coordinates.
IntPoint m_lastKnownMousePosition;
IntPoint m_lastKnownMouseGlobalPosition;
unsigned m_isMousePositionUnknown : 1;
// Current button-press state for mouse/mouse-like-stylus.
// TODO(crbug.com/563676): Buggy for chorded buttons.
unsigned m_mousePressed : 1;
unsigned m_mouseDownMayStartAutoscroll : 1;
unsigned m_svgPan : 1;
unsigned m_capturesDragging : 1;
unsigned m_mouseDownMayStartDrag : 1;
Member<Node> m_mousePressNode;
int m_clickCount;
Member<Node> m_clickNode;
IntPoint m_mouseDownPos; // In our view's coords.
double m_mouseDownTimestamp;
PlatformMouseEvent m_mouseDown;
LayoutPoint m_dragStartPos;
Timer<MouseEventManager> m_fakeMouseMoveEventTimer;
};
} // namespace blink
#endif // MouseEventManager_h