summaryrefslogtreecommitdiff
path: root/chromium/third_party/WebKit/Source/core/input/MouseEventManager.h
blob: 6f56ed44ee71d08e236d55c9856ead67b4d30ba1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// 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/dom/SynchronousMutationObserver.h"
#include "core/input/BoundaryEventDispatcher.h"
#include "core/page/DragActions.h"
#include "core/page/EventWithHitTestResults.h"
#include "platform/Timer.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/Time.h"
#include "public/platform/WebInputEventResult.h"
#include "public/platform/WebMouseEvent.h"

namespace blink {

class ContainerNode;
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 final
    : public GarbageCollectedFinalized<MouseEventManager>,
      public SynchronousMutationObserver {
  WTF_MAKE_NONCOPYABLE(MouseEventManager);
  USING_GARBAGE_COLLECTED_MIXIN(MouseEventManager);

 public:
  MouseEventManager(LocalFrame&, ScrollManager&);
  virtual ~MouseEventManager();
  DECLARE_TRACE();

  enum FakeMouseMoveReason { kDuringScroll, kPerFrame };

  WebInputEventResult DispatchMouseEvent(EventTarget*,
                                         const AtomicString&,
                                         const WebMouseEvent&,
                                         const String& canvas_region_id,
                                         EventTarget* related_target,
                                         bool check_for_listener = false);

  WebInputEventResult SetMousePositionAndDispatchMouseEvent(
      Node* target_node,
      const String& canvas_region_id,
      const AtomicString& event_type,
      const WebMouseEvent&);

  WebInputEventResult DispatchMouseClickIfNeeded(
      const MouseEventWithHitTestResults&,
      Element& mouse_release_target);

  WebInputEventResult DispatchDragSrcEvent(const AtomicString& event_type,
                                           const WebMouseEvent&);
  WebInputEventResult DispatchDragEvent(const AtomicString& event_type,
                                        Node* target,
                                        Node* related_target,
                                        const WebMouseEvent&,
                                        DataTransfer*);

  // Resets the internal state of this object.
  void Clear();

  void SendBoundaryEvents(EventTarget* exited_target,
                          EventTarget* entered_target,
                          const String& canvas_region_id,
                          const WebMouseEvent&);

  void SetNodeUnderMouse(Node*,
                         const String& canvas_region_id,
                         const WebMouseEvent&);

  WebInputEventResult HandleMouseFocus(
      const HitTestResult&,
      InputDeviceCapabilities* source_capabilities);

  void FakeMouseMoveEventTimerFired(TimerBase*);

  void CancelFakeMouseMoveEvent();
  void DispatchFakeMouseMoveEventSoon(MouseEventManager::FakeMouseMoveReason);
  void DispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);

  void SetLastKnownMousePosition(const WebMouseEvent&);
  void SetLastMousePositionAsUnknown();

  bool HandleDragDropIfPossible(const GestureEventWithHitTestResults&);

  WebInputEventResult HandleMouseDraggedEvent(
      const MouseEventWithHitTestResults&);
  WebInputEventResult HandleMousePressEvent(
      const MouseEventWithHitTestResults&);
  WebInputEventResult HandleMouseReleaseEvent(
      const MouseEventWithHitTestResults&);

  DragState& GetDragState();

  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 WebMouseEvent&, DragOperation);

  void UpdateSelectionForMouseDrag();

  void HandleMousePressEventUpdateStates(const WebMouseEvent&);
  void HandleMouseReleaseEventUpdateStates();

  // Returns whether pan is handled and resets the state on release.
  bool HandleSvgPanIfNeeded(bool is_release_event);

  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();
  // TODO(aelias): Make LastKnownMousePosition return FloatPoint.
  IntPoint LastKnownMousePosition();
  FloatPoint LastKnownMousePositionGlobal();

  bool MousePressed();
  void SetMousePressed(bool);

  bool CapturesDragging() const;
  void SetCapturesDragging(bool);

  void SetMouseDownMayStartAutoscroll() {
    mouse_down_may_start_autoscroll_ = true;
  }

  Node* MousePressNode();
  void SetMousePressNode(Node*);

  void SetClickElement(Element*);
  void SetClickCount(int);

  bool MouseDownMayStartDrag();

  bool FakeMouseMovePending() const;

 private:
  class MouseEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
    WTF_MAKE_NONCOPYABLE(MouseEventBoundaryEventDispatcher);

   public:
    MouseEventBoundaryEventDispatcher(MouseEventManager*,
                                      const WebMouseEvent*,
                                      EventTarget* exited_target,
                                      const String& canvas_region_id);

   protected:
    void DispatchOut(EventTarget*, EventTarget* related_target) override;
    void DispatchOver(EventTarget*, EventTarget* related_target) override;
    void DispatchLeave(EventTarget*,
                       EventTarget* related_target,
                       bool check_for_listener) override;
    void DispatchEnter(EventTarget*,
                       EventTarget* related_target,
                       bool check_for_listener) override;
    AtomicString GetLeaveEvent() override;
    AtomicString GetEnterEvent() override;

   private:
    void Dispatch(EventTarget*,
                  EventTarget* related_target,
                  const AtomicString&,
                  const String& canvas_region_id,
                  const WebMouseEvent&,
                  bool check_for_listener);
    Member<MouseEventManager> mouse_event_manager_;
    const WebMouseEvent* web_mouse_event_;
    Member<EventTarget> exited_target_;
    String canvas_region_id_;
  };

  // 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 DragThresholdExceeded(const IntPoint&) const;
  bool HandleDrag(const MouseEventWithHitTestResults&, DragInitiator);
  bool TryStartDrag(const MouseEventWithHitTestResults&);
  void ClearDragDataTransfer();
  DataTransfer* CreateDraggingDataTransfer() const;

  void ResetDragState();

  // Implementations of |SynchronousMutationObserver|
  void NodeChildrenWillBeRemoved(ContainerNode&) final;
  void NodeWillBeRemoved(Node& node_to_be_removed) final;

  // NOTE: If adding a new field to this class please ensure that it is
  // cleared in |MouseEventManager::clear()|.

  const Member<LocalFrame> frame_;
  Member<ScrollManager> scroll_manager_;

  // 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> node_under_mouse_;

  // The last mouse movement position this frame has seen in root frame
  // coordinates.
  FloatPoint last_known_mouse_position_;
  FloatPoint last_known_mouse_global_position_;

  unsigned is_mouse_position_unknown_ : 1;
  // Current button-press state for mouse/mouse-like-stylus.
  // TODO(crbug.com/563676): Buggy for chorded buttons.
  unsigned mouse_pressed_ : 1;

  unsigned mouse_down_may_start_autoscroll_ : 1;
  unsigned svg_pan_ : 1;
  unsigned captures_dragging_ : 1;
  unsigned mouse_down_may_start_drag_ : 1;

  Member<Node> mouse_press_node_;

  int click_count_;
  Member<Element> click_element_;
  // This element should be mostly the same as click_element_. Only when
  // click_element_ is set to null due to DOM manipulation mouse_down_element_
  // remains unchanged.
  Member<Element> mouse_down_element_;

  IntPoint mouse_down_pos_;  // In our view's coords.
  TimeTicks mouse_down_timestamp_;
  WebMouseEvent mouse_down_;

  LayoutPoint drag_start_pos_;

  TaskRunnerTimer<MouseEventManager> fake_mouse_move_event_timer_;
};

}  // namespace blink

#endif  // MouseEventManager_h