Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: third_party/WebKit/Source/core/input/GestureManager.cpp

Issue 2137113002: Create GestureManager class and move related logic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make GestureManager friend of EventHandler Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/input/GestureManager.h"
6
7 #include "core/dom/Document.h"
8 #include "core/editing/SelectionController.h"
9 #include "core/events/GestureEvent.h"
10 #include "core/frame/FrameHost.h"
11 #include "core/frame/FrameView.h"
12 #include "core/frame/Settings.h"
13 #include "core/frame/VisualViewport.h"
14 #include "core/input/EventHandler.h"
15 #include "core/page/ChromeClient.h"
16 #include "core/page/Page.h"
17
18 namespace blink {
19
20 GestureManager::GestureManager(LocalFrame* frame, ScrollManager* scrollManager,
21 PointerEventManager* pointerEventManager,
22 SelectionController* selectionController)
23 : m_frame(frame)
24 , m_scrollManager(scrollManager)
dtapuska 2016/07/13 12:19:28 This looks like a wacky indent. Is this what git c
Navid Zolghadr 2016/07/13 16:28:14 Done.
25 , m_pointerEventManager(pointerEventManager)
26 , m_selectionController(selectionController)
27 {
28 clear();
29 }
30
31 GestureManager::~GestureManager()
32 {
33 }
34
35 void GestureManager::clear()
36 {
37 m_suppressMouseEventsFromGestures = false;
38 m_longTapShouldInvokeContextMenu = false;
39 m_lastShowPressTimestamp = 0;
40 }
41
42 DEFINE_TRACE(GestureManager)
43 {
44 visitor->trace(m_frame);
45 visitor->trace(m_selectionController);
46 }
47
48 HitTestRequest::HitTestRequestType GestureManager::getHitTypeForGestureType(Plat formEvent::EventType type)
49 {
50 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent;
51 switch (type) {
52 case PlatformEvent::GestureShowPress:
53 case PlatformEvent::GestureTapUnconfirmed:
54 return hitType | HitTestRequest::Active;
55 case PlatformEvent::GestureTapDownCancel:
56 // A TapDownCancel received when no element is active shouldn't really b e changing hover state.
57 if (!m_frame->document()->activeHoverElement())
58 hitType |= HitTestRequest::ReadOnly;
59 return hitType | HitTestRequest::Release;
60 case PlatformEvent::GestureTap:
61 return hitType | HitTestRequest::Release;
62 case PlatformEvent::GestureTapDown:
63 case PlatformEvent::GestureLongPress:
64 case PlatformEvent::GestureLongTap:
65 case PlatformEvent::GestureTwoFingerTap:
66 // FIXME: Shouldn't LongTap and TwoFingerTap clear the Active state?
67 return hitType | HitTestRequest::Active | HitTestRequest::ReadOnly;
68 default:
69 NOTREACHED();
70 return hitType | HitTestRequest::Active | HitTestRequest::ReadOnly;
71 }
72 }
73
74 WebInputEventResult GestureManager::handleGestureEventInFrame(const GestureEvent WithHitTestResults& targetedEvent)
75 {
76 DCHECK(!targetedEvent.event().isScrollEvent());
77
78 Node* eventTarget = targetedEvent.hitTestResult().innerNode();
79 const PlatformGestureEvent& gestureEvent = targetedEvent.event();
80
81 if (m_scrollManager->canHandleGestureEvent(targetedEvent))
82 return WebInputEventResult::HandledSuppressed;
83
84 if (eventTarget) {
85 GestureEvent* gestureDomEvent = GestureEvent::create(eventTarget->docume nt().domWindow(), gestureEvent);
86 if (gestureDomEvent) {
87 DispatchEventResult gestureDomEventResult = eventTarget->dispatchEve nt(gestureDomEvent);
88 if (gestureDomEventResult != DispatchEventResult::NotCanceled) {
89 DCHECK(gestureDomEventResult != DispatchEventResult::CanceledByE ventHandler);
90 return EventHandler::toWebInputEventResult(gestureDomEventResult );
91 }
92 }
93 }
94
95 switch (gestureEvent.type()) {
96 case PlatformEvent::GestureTapDown:
97 return handleGestureTapDown(targetedEvent);
98 case PlatformEvent::GestureTap:
99 return handleGestureTap(targetedEvent);
100 case PlatformEvent::GestureShowPress:
101 return handleGestureShowPress();
102 case PlatformEvent::GestureLongPress:
103 return handleGestureLongPress(targetedEvent);
104 case PlatformEvent::GestureLongTap:
105 return handleGestureLongTap(targetedEvent);
106 case PlatformEvent::GestureTwoFingerTap:
107 return m_frame->eventHandler().sendContextMenuEventForGesture(targetedEv ent);
108 case PlatformEvent::GesturePinchBegin:
109 case PlatformEvent::GesturePinchEnd:
110 case PlatformEvent::GesturePinchUpdate:
111 case PlatformEvent::GestureTapDownCancel:
112 case PlatformEvent::GestureTapUnconfirmed:
113 break;
114 default:
115 NOTREACHED();
116 }
117
118 return WebInputEventResult::NotHandled;
119 }
120
121 WebInputEventResult GestureManager::handleGestureTapDown(const GestureEventWithH itTestResults& targetedEvent)
122 {
123 m_suppressMouseEventsFromGestures =
124 m_pointerEventManager->primaryPointerdownCanceled(targetedEvent.event(). uniqueTouchEventId());
125 return WebInputEventResult::NotHandled;
126 }
127
128 WebInputEventResult GestureManager::handleGestureTap(const GestureEventWithHitTe stResults& targetedEvent)
129 {
130 FrameView* frameView(m_frame->view());
131 const PlatformGestureEvent& gestureEvent = targetedEvent.event();
132 HitTestRequest::HitTestRequestType hitType = getHitTypeForGestureType(gestur eEvent.type());
133 uint64_t preDispatchDomTreeVersion = m_frame->document()->domTreeVersion();
134 uint64_t preDispatchStyleVersion = m_frame->document()->styleVersion();
135
136 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
137
138 HitTestResult currentHitTest = targetedEvent.hitTestResult();
139
140 // We use the adjusted position so the application isn't surprised to see a event with
141 // co-ordinates outside the target's bounds.
142 IntPoint adjustedPoint = frameView->rootFrameToContents(gestureEvent.positio n());
143
144 const unsigned modifiers = gestureEvent.getModifiers();
145
146 if (!m_suppressMouseEventsFromGestures) {
147 PlatformMouseEvent fakeMouseMove(gestureEvent.position(), gestureEvent.g lobalPosition(),
148 NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0,
149 static_cast<PlatformEvent::Modifiers>(modifiers),
150 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerP roperties::PointerType::Mouse);
151 m_frame->eventHandler().dispatchMouseEvent(EventTypeNames::mousemove, cu rrentHitTest.innerNode(), 0, fakeMouseMove);
152 }
153
154 // Do a new hit-test in case the mousemove event changed the DOM.
155 // Note that if the original hit test wasn't over an element (eg. was over a scrollbar) we
156 // don't want to re-hit-test because it may be in the wrong frame (and there 's no way the page
157 // could have seen the event anyway).
158 // Also note that the position of the frame may have changed, so we need to recompute the content
159 // co-ordinates (updating layout/style as hitTestResultAtPoint normally woul d).
160 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920
161 if (currentHitTest.innerNode()) {
162 LocalFrame* mainFrame = m_frame->localFrameRoot();
163 if (mainFrame && mainFrame->view())
164 mainFrame->view()->updateLifecycleToCompositingCleanPlusScrolling();
165 adjustedPoint = frameView->rootFrameToContents(gestureEvent.position());
166 currentHitTest = EventHandler::hitTestResultInFrame(m_frame, adjustedPoi nt, hitType);
167 }
168
169 // Capture data for showUnhandledTapUIIfNeeded.
170 Node* tappedNode = currentHitTest.innerNode();
171 IntPoint tappedPosition = gestureEvent.position();
172 Node* tappedNonTextNode = tappedNode;
173
174 if (tappedNonTextNode && tappedNonTextNode->isTextNode())
175 tappedNonTextNode = FlatTreeTraversal::parent(*tappedNonTextNode);
176
177 m_frame->eventHandler().setClickNode(tappedNonTextNode);
178
179 PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globa lPosition(),
180 LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(),
181 static_cast<PlatformEvent::Modifiers>(modifiers | PlatformEvent::LeftBut tonDown),
182 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerPrope rties::PointerType::Mouse);
183
184 // TODO(mustaq): We suppress MEs plus all it's side effects. What would that
185 // mean for for TEs? What's the right balance here? crbug.com/617255
186 WebInputEventResult mouseDownEventResult = WebInputEventResult::HandledSuppr essed;
187 if (!m_suppressMouseEventsFromGestures) {
188 mouseDownEventResult = m_frame->eventHandler().dispatchMouseEvent(EventT ypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMo useDown);
189 m_selectionController->initializeSelectionState();
190 if (mouseDownEventResult == WebInputEventResult::NotHandled)
191 mouseDownEventResult = m_frame->eventHandler().handleMouseFocus(Mous eEventWithHitTestResults(fakeMouseDown, currentHitTest), InputDeviceCapabilities ::firesTouchEventsSourceCapabilities());
192 if (mouseDownEventResult == WebInputEventResult::NotHandled)
193 mouseDownEventResult = m_frame->eventHandler().handleMousePressEvent (MouseEventWithHitTestResults(fakeMouseDown, currentHitTest));
194 }
195
196 if (currentHitTest.innerNode()) {
197 DCHECK(gestureEvent.type() == PlatformEvent::GestureTap);
198 HitTestResult result = currentHitTest;
199 result.setToShadowHostIfInUserAgentShadowRoot();
200 m_frame->chromeClient().onMouseDown(result.innerNode());
201 }
202
203 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920
204 if (currentHitTest.innerNode()) {
205 LocalFrame* mainFrame = m_frame->localFrameRoot();
206 if (mainFrame && mainFrame->view())
207 mainFrame->view()->updateAllLifecyclePhases();
208 adjustedPoint = frameView->rootFrameToContents(gestureEvent.position());
209 currentHitTest = EventHandler::hitTestResultInFrame(m_frame, adjustedPoi nt, hitType);
210 }
211
212 PlatformMouseEvent fakeMouseUp(gestureEvent.position(), gestureEvent.globalP osition(),
213 LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(),
214 static_cast<PlatformEvent::Modifiers>(modifiers),
215 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerPrope rties::PointerType::Mouse);
216 WebInputEventResult mouseUpEventResult = m_suppressMouseEventsFromGestures
217 ? WebInputEventResult::HandledSuppressed
218 : m_frame->eventHandler().dispatchMouseEvent(EventTypeNames::mouseup, cu rrentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp);
219
220 WebInputEventResult clickEventResult = WebInputEventResult::NotHandled;
221 if (tappedNonTextNode) {
222 if (currentHitTest.innerNode()) {
223 // Updates distribution because a mouseup (or mousedown) event liste ner can make the
224 // tree dirty at dispatchMouseEvent() invocation above.
225 // Unless distribution is updated, commonAncestor would hit DCHECK.
226 // Both tappedNonTextNode and currentHitTest.innerNode()) don't need to be updated
227 // because commonAncestor() will exit early if their documents are d ifferent.
228 tappedNonTextNode->updateDistribution();
229 Node* clickTargetNode = currentHitTest.innerNode()->commonAncestor(* tappedNonTextNode, EventHandler::parentForClickEvent);
230 clickEventResult = m_frame->eventHandler().dispatchMouseEvent(EventT ypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp);
231 }
232 m_frame->eventHandler().setClickNode(nullptr);
233 }
234
235 if (mouseUpEventResult == WebInputEventResult::NotHandled)
236 mouseUpEventResult = m_frame->eventHandler().handleMouseReleaseEvent(Mou seEventWithHitTestResults(fakeMouseUp, currentHitTest));
237 m_frame->eventHandler().clearDragHeuristicState();
238
239 WebInputEventResult eventResult = EventHandler::mergeEventResult(EventHandle r::mergeEventResult(mouseDownEventResult, mouseUpEventResult), clickEventResult) ;
240 if (eventResult == WebInputEventResult::NotHandled && tappedNode && m_frame- >page()) {
241 bool domTreeChanged = preDispatchDomTreeVersion != m_frame->document()-> domTreeVersion();
242 bool styleChanged = preDispatchStyleVersion != m_frame->document()->styl eVersion();
243
244 IntPoint tappedPositionInViewport = frameHost()->visualViewport().rootFr ameToViewport(tappedPosition);
245 m_frame->chromeClient().showUnhandledTapUIIfNeeded(tappedPositionInViewp ort, tappedNode, domTreeChanged || styleChanged);
246 }
247 return eventResult;
248 }
249
250 WebInputEventResult GestureManager::handleGestureLongPress(const GestureEventWit hHitTestResults& targetedEvent)
251 {
252 const PlatformGestureEvent& gestureEvent = targetedEvent.event();
253
254 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests here (re-using the
255 // supplied HitTestResult), but that will require some overhaul of the touch drag-and-drop code
256 // and LongPress is such a special scenario that it's unlikely to matter muc h in practice.
257
258 m_longTapShouldInvokeContextMenu = false;
259 if (m_frame->eventHandler().handleDragDropIfPossible(targetedEvent)) {
260 m_longTapShouldInvokeContextMenu = true;
261 return WebInputEventResult::HandledSystem;
262 }
263 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po sition());
264 HitTestResult result = m_frame->eventHandler().hitTestResultAtPoint(hitTestP oint);
265 if (m_selectionController->handleGestureLongPress(gestureEvent, result)) {
266 m_frame->eventHandler().focusDocumentView();
267 return WebInputEventResult::HandledSystem;
268 }
269
270 return m_frame->eventHandler().sendContextMenuEventForGesture(targetedEvent) ;
271 }
272
273 WebInputEventResult GestureManager::handleGestureLongTap(const GestureEventWithH itTestResults& targetedEvent)
274 {
275 #if !OS(ANDROID)
276 if (m_longTapShouldInvokeContextMenu) {
277 m_longTapShouldInvokeContextMenu = false;
278 return m_frame->eventHandler().sendContextMenuEventForGesture(targetedEv ent);
279 }
280 #endif
281 return WebInputEventResult::NotHandled;
282 }
283
284 WebInputEventResult GestureManager::handleGestureShowPress()
285 {
286 m_lastShowPressTimestamp = WTF::monotonicallyIncreasingTime();
287
288 FrameView* view = m_frame->view();
289 if (!view)
290 return WebInputEventResult::NotHandled;
291 if (ScrollAnimatorBase* scrollAnimator = view->existingScrollAnimator())
292 scrollAnimator->cancelAnimation();
293 const FrameView::ScrollableAreaSet* areas = view->scrollableAreas();
294 if (!areas)
295 return WebInputEventResult::NotHandled;
296 for (const ScrollableArea* scrollableArea : *areas) {
297 ScrollAnimatorBase* animator = scrollableArea->existingScrollAnimator();
298 if (animator)
299 animator->cancelAnimation();
300 }
301 return WebInputEventResult::NotHandled;
302 }
303
304
305 FrameHost* GestureManager::frameHost() const
306 {
307 if (!m_frame->page())
308 return nullptr;
309
310 return &m_frame->page()->frameHost();
311 }
312
313 double GestureManager::getLastShowPressTimestamp()
314 {
315 return m_lastShowPressTimestamp;
316 }
317
318 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698