summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/input/pointer_event_manager.h
blob: 9636ca58ec1fa817471c72c1e04ba3cd964840e7 (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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// 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 THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_POINTER_EVENT_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_POINTER_EVENT_MANAGER_H_

#include "base/macros.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_pointer_properties.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/events/pointer_event_factory.h"
#include "third_party/blink/renderer/core/input/boundary_event_dispatcher.h"
#include "third_party/blink/renderer/core/input/touch_event_manager.h"
#include "third_party/blink/renderer/core/page/touch_adjustment.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.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> {
 public:
  PointerEventManager(LocalFrame&, MouseEventManager&);
  void Trace(blink::Visitor*);

  // This is the unified path for handling all input device events. This may
  // cause firing DOM pointerevents, mouseevent, and touch events accordingly.
  // TODO(crbug.com/625841): We need to get all event handling path to go
  // through this function.
  WebInputEventResult HandlePointerEvent(
      const WebPointerEvent&,
      const Vector<WebPointerEvent>& coalesced_events);

  // 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 String& canvas_region_id,
      const WebInputEvent::Type,
      const WebMouseEvent&,
      const Vector<WebMouseEvent>& coalesced_events);

  // 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* entered_node,
                                         const String& canvas_region_id,
                                         const WebMouseEvent&);

  WebInputEventResult DirectDispatchMousePointerEvent(
      Node* target,
      const WebMouseEvent&,
      const AtomicString& event_type,
      const Vector<WebMouseEvent>& coalesced_events,
      const String& canvas_node_id = String());

  WebInputEventResult CreateAndDispatchPointerEvent(
      Node* target,
      const AtomicString& mouse_event_name,
      const WebMouseEvent&,
      const Vector<WebMouseEvent>& coalesced_events);

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

  void ElementRemoved(EventTarget*);

  void SetPointerCapture(int, EventTarget*);
  void ReleasePointerCapture(int, EventTarget*);
  void ReleaseMousePointerCapture();

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

  // Returns whether pointerId is for an active touch pointerevent and whether
  // the last event was sent to the given frame.
  bool IsTouchPointerIdActiveOnFrame(int, LocalFrame*) const;

  // Returns true if the primary pointerdown corresponding to the given
  // |uniqueTouchEventId| was canceled. Also drops stale ids from
  // |m_touchIdsForCanceledPointerdowns|.
  bool PrimaryPointerdownCanceled(uint32_t unique_touch_event_id);

  void ProcessPendingPointerCaptureForPointerLock(const WebMouseEvent&);

  // Sends any outstanding events. For example it notifies TouchEventManager
  // to group any changes to touch since last FlushEvents and send the touch
  // event out to js. Since after this function any outstanding event is sent,
  // it also clears any state that might have kept since the last call to this
  // function.
  WebInputEventResult FlushEvents();

 private:
  typedef HeapHashMap<int,
                      Member<EventTarget>,
                      WTF::IntHash<int>,
                      WTF::UnsignedWithZeroKeyHashTraits<int>>
      PointerCapturingMap;
  class EventTargetAttributes {
    DISALLOW_NEW();

   public:
    void Trace(blink::Visitor* visitor) { visitor->Trace(target); }
    Member<EventTarget> target;
    EventTargetAttributes() : target(nullptr) {}
    EventTargetAttributes(EventTarget* target)
        : target(target) {}
  };

  class PointerEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
   public:
    PointerEventBoundaryEventDispatcher(PointerEventManager*, PointerEvent*);

   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&,
                  bool check_for_listener);
    Member<PointerEventManager> pointer_event_manager_;
    Member<PointerEvent> pointer_event_;
    DISALLOW_COPY_AND_ASSIGN(PointerEventBoundaryEventDispatcher);
  };

  // Sends pointercancels for existing PointerEvents that are interrupted.
  // For example when browser starts dragging with mouse or when we start
  // scrolling with scroll capable pointers pointercancel events should be
  // dispatched for those. Also sets initial states accordingly so the
  // following events in that stream don't generate pointerevents (e.g.
  // in the scrolling case which scroll starts and pointerevents stop and
  // touchevents continue to fire).
  void HandlePointerInterruption(const WebPointerEvent&);

  // Returns PointerEventTarget for a WebTouchPoint, hit-testing as necessary.
  EventHandlingUtil::PointerEventTarget ComputePointerEventTarget(
      const WebPointerEvent&);

  WebInputEventResult DispatchTouchPointerEvent(
      const WebPointerEvent&,
      const Vector<WebPointerEvent>& coalesced_events,
      const EventHandlingUtil::PointerEventTarget&);

  // Returns whether the event is consumed or not.
  WebInputEventResult SendTouchPointerEvent(EventTarget*,
                                            PointerEvent*,
                                            bool hovering);

  void SendBoundaryEvents(EventTarget* exited_target,
                          EventTarget* entered_target,
                          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* hit_test_target,
      const String& canvas_region_id = String(),
      const WebMouseEvent* = nullptr);

  void RemoveTargetFromPointerCapturingMapping(PointerCapturingMap&,
                                               const EventTarget*);
  EventTarget* GetEffectiveTargetForPointerEvent(EventTarget*, int);
  EventTarget* GetCapturingNode(int);
  void RemovePointer(PointerEvent*);
  WebInputEventResult DispatchPointerEvent(EventTarget*,
                                           PointerEvent*,
                                           bool check_for_listener = false);
  void ReleasePointerCapture(int);
  // Returns true if capture target and pending capture target were different.
  bool GetPointerCaptureState(int pointer_id,
                              EventTarget** pointer_capture_target,
                              EventTarget** pending_pointer_capture_target);

  // Only adjust touch type primary pointer down.
  bool ShouldAdjustPointerEvent(const WebPointerEvent&) const;
  // Adjust coordinates so it can be used to find the best clickable target.
  void AdjustTouchPointerEvent(WebPointerEvent&);

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

  const Member<LocalFrame> 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 prevent_mouse_event_for_pointer_type_
      [static_cast<size_t>(WebPointerProperties::PointerType::kLastEntry) + 1];

  // Set upon scrolling starts when sending a pointercancel, prevents PE
  // dispatches for non-hovering pointers until all of them become inactive.
  bool non_hovering_pointers_canceled_;

  Deque<uint32_t> touch_ids_for_canceled_pointerdowns_;

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

  PointerCapturingMap pointer_capture_target_;
  PointerCapturingMap pending_pointer_capture_target_;

  PointerEventFactory pointer_event_factory_;
  Member<TouchEventManager> touch_event_manager_;
  Member<MouseEventManager> mouse_event_manager_;

  // TODO(crbug.com/789643): If we go with one token for pointerevent and one
  // for touch events then we can remove this class field.
  // It keeps the shared user gesture token between DOM touch events and
  // pointerevents. It gets created at first when this class gets notified of
  // the appropriate pointerevent and it must be cleared after the corresponding
  // touch event is sent (i.e. after FlushEvents).
  std::unique_ptr<UserGestureIndicator> user_gesture_holder_;

  // The pointerId of the PointerEvent currently being dispatched within this
  // frame or 0 if none.
  int dispatching_pointer_id_;

  DISALLOW_COPY_AND_ASSIGN(PointerEventManager);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_POINTER_EVENT_MANAGER_H_