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

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: Fix the nits 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)
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 = m_pointerEventManager->primaryPointerdow nCanceled(targetedEvent.event().uniqueTouchEventId());
124 return WebInputEventResult::NotHandled;
125 }
126
127 WebInputEventResult GestureManager::handleGestureTap(const GestureEventWithHitTe stResults& targetedEvent)
128 {
129 FrameView* frameView(m_frame->view());
130 const PlatformGestureEvent& gestureEvent = targetedEvent.event();
131 HitTestRequest::HitTestRequestType hitType = getHitTypeForGestureType(gestur eEvent.type());
132 uint64_t preDispatchDomTreeVersion = m_frame->document()->domTreeVersion();
133 uint64_t preDispatchStyleVersion = m_frame->document()->styleVersion();
134
135 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
136
137 HitTestResult currentHitTest = targetedEvent.hitTestResult();
138
139 // We use the adjusted position so the application isn't surprised to see a event with
140 // co-ordinates outside the target's bounds.
141 IntPoint adjustedPoint = frameView->rootFrameToContents(gestureEvent.positio n());
142
143 const unsigned modifiers = gestureEvent.getModifiers();
144
145 if (!m_suppressMouseEventsFromGestures) {
146 PlatformMouseEvent fakeMouseMove(gestureEvent.position(), gestureEvent.g lobalPosition(),
147 NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0,
148 static_cast<PlatformEvent::Modifiers>(modifiers),
149 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerP roperties::PointerType::Mouse);
150 m_frame->eventHandler().dispatchMouseEvent(EventTypeNames::mousemove, cu rrentHitTest.innerNode(), 0, fakeMouseMove);
151 }
152
153 // Do a new hit-test in case the mousemove event changed the DOM.
154 // Note that if the original hit test wasn't over an element (eg. was over a scrollbar) we
155 // don't want to re-hit-test because it may be in the wrong frame (and there 's no way the page
156 // could have seen the event anyway).
157 // Also note that the position of the frame may have changed, so we need to recompute the content
158 // co-ordinates (updating layout/style as hitTestResultAtPoint normally woul d).
159 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920
160 if (currentHitTest.innerNode()) {
161 LocalFrame* mainFrame = m_frame->localFrameRoot();
162 if (mainFrame && mainFrame->view())
163 mainFrame->view()->updateLifecycleToCompositingCleanPlusScrolling();
164 adjustedPoint = frameView->rootFrameToContents(gestureEvent.position());
165 currentHitTest = EventHandler::hitTestResultInFrame(m_frame, adjustedPoi nt, hitType);
166 }
167
168 // Capture data for showUnhandledTapUIIfNeeded.
169 Node* tappedNode = currentHitTest.innerNode();
170 IntPoint tappedPosition = gestureEvent.position();
171 Node* tappedNonTextNode = tappedNode;
172
173 if (tappedNonTextNode && tappedNonTextNode->isTextNode())
174 tappedNonTextNode = FlatTreeTraversal::parent(*tappedNonTextNode);
175
176 m_frame->eventHandler().setClickNode(tappedNonTextNode);
177
178 PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globa lPosition(),
179 LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(),
180 static_cast<PlatformEvent::Modifiers>(modifiers | PlatformEvent::LeftBut tonDown),
181 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerPrope rties::PointerType::Mouse);
182
183 // TODO(mustaq): We suppress MEs plus all it's side effects. What would that
184 // mean for for TEs? What's the right balance here? crbug.com/617255
185 WebInputEventResult mouseDownEventResult = WebInputEventResult::HandledSuppr essed;
186 if (!m_suppressMouseEventsFromGestures) {
187 mouseDownEventResult = m_frame->eventHandler().dispatchMouseEvent(EventT ypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMo useDown);
188 m_selectionController->initializeSelectionState();
189 if (mouseDownEventResult == WebInputEventResult::NotHandled)
190 mouseDownEventResult = m_frame->eventHandler().handleMouseFocus(Mous eEventWithHitTestResults(fakeMouseDown, currentHitTest), InputDeviceCapabilities ::firesTouchEventsSourceCapabilities());
191 if (mouseDownEventResult == WebInputEventResult::NotHandled)
192 mouseDownEventResult = m_frame->eventHandler().handleMousePressEvent (MouseEventWithHitTestResults(fakeMouseDown, currentHitTest));
193 }
194
195 if (currentHitTest.innerNode()) {
196 DCHECK(gestureEvent.type() == PlatformEvent::GestureTap);
197 HitTestResult result = currentHitTest;
198 result.setToShadowHostIfInUserAgentShadowRoot();
199 m_frame->chromeClient().onMouseDown(result.innerNode());
200 }
201
202 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920
203 if (currentHitTest.innerNode()) {
204 LocalFrame* mainFrame = m_frame->localFrameRoot();
205 if (mainFrame && mainFrame->view())
206 mainFrame->view()->updateAllLifecyclePhases();
207 adjustedPoint = frameView->rootFrameToContents(gestureEvent.position());
208 currentHitTest = EventHandler::hitTestResultInFrame(m_frame, adjustedPoi nt, hitType);
209 }
210
211 PlatformMouseEvent fakeMouseUp(gestureEvent.position(), gestureEvent.globalP osition(),
212 LeftButton, PlatformEvent::MouseReleased, gestureEvent.tapCount(),
213 static_cast<PlatformEvent::Modifiers>(modifiers),
214 PlatformMouseEvent::FromTouch, gestureEvent.timestamp(), WebPointerPrope rties::PointerType::Mouse);
215 WebInputEventResult mouseUpEventResult = m_suppressMouseEventsFromGestures
216 ? WebInputEventResult::HandledSuppressed
217 : m_frame->eventHandler().dispatchMouseEvent(EventTypeNames::mouseup, cu rrentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseUp);
218
219 WebInputEventResult clickEventResult = WebInputEventResult::NotHandled;
220 if (tappedNonTextNode) {
221 if (currentHitTest.innerNode()) {
222 // Updates distribution because a mouseup (or mousedown) event liste ner can make the
223 // tree dirty at dispatchMouseEvent() invocation above.
224 // Unless distribution is updated, commonAncestor would hit DCHECK.
225 // Both tappedNonTextNode and currentHitTest.innerNode()) don't need to be updated
226 // because commonAncestor() will exit early if their documents are d ifferent.
227 tappedNonTextNode->updateDistribution();
228 Node* clickTargetNode = currentHitTest.innerNode()->commonAncestor(* tappedNonTextNode, EventHandler::parentForClickEvent);
229 clickEventResult = m_frame->eventHandler().dispatchMouseEvent(EventT ypeNames::click, clickTargetNode, gestureEvent.tapCount(), fakeMouseUp);
230 }
231 m_frame->eventHandler().setClickNode(nullptr);
232 }
233
234 if (mouseUpEventResult == WebInputEventResult::NotHandled)
235 mouseUpEventResult = m_frame->eventHandler().handleMouseReleaseEvent(Mou seEventWithHitTestResults(fakeMouseUp, currentHitTest));
236 m_frame->eventHandler().clearDragHeuristicState();
237
238 WebInputEventResult eventResult = EventHandler::mergeEventResult(EventHandle r::mergeEventResult(mouseDownEventResult, mouseUpEventResult), clickEventResult) ;
239 if (eventResult == WebInputEventResult::NotHandled && tappedNode && m_frame- >page()) {
240 bool domTreeChanged = preDispatchDomTreeVersion != m_frame->document()-> domTreeVersion();
241 bool styleChanged = preDispatchStyleVersion != m_frame->document()->styl eVersion();
242
243 IntPoint tappedPositionInViewport = frameHost()->visualViewport().rootFr ameToViewport(tappedPosition);
244 m_frame->chromeClient().showUnhandledTapUIIfNeeded(tappedPositionInViewp ort, tappedNode, domTreeChanged || styleChanged);
245 }
246 return eventResult;
247 }
248
249 WebInputEventResult GestureManager::handleGestureLongPress(const GestureEventWit hHitTestResults& targetedEvent)
250 {
251 const PlatformGestureEvent& gestureEvent = targetedEvent.event();
252
253 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests here (re-using the
254 // supplied HitTestResult), but that will require some overhaul of the touch drag-and-drop code
255 // and LongPress is such a special scenario that it's unlikely to matter muc h in practice.
256
257 m_longTapShouldInvokeContextMenu = false;
258 if (m_frame->eventHandler().handleDragDropIfPossible(targetedEvent)) {
259 m_longTapShouldInvokeContextMenu = true;
260 return WebInputEventResult::HandledSystem;
261 }
262 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po sition());
263 HitTestResult result = m_frame->eventHandler().hitTestResultAtPoint(hitTestP oint);
264 if (m_selectionController->handleGestureLongPress(gestureEvent, result)) {
265 m_frame->eventHandler().focusDocumentView();
266 return WebInputEventResult::HandledSystem;
267 }
268
269 return m_frame->eventHandler().sendContextMenuEventForGesture(targetedEvent) ;
270 }
271
272 WebInputEventResult GestureManager::handleGestureLongTap(const GestureEventWithH itTestResults& targetedEvent)
273 {
274 #if !OS(ANDROID)
275 if (m_longTapShouldInvokeContextMenu) {
276 m_longTapShouldInvokeContextMenu = false;
277 return m_frame->eventHandler().sendContextMenuEventForGesture(targetedEv ent);
278 }
279 #endif
280 return WebInputEventResult::NotHandled;
281 }
282
283 WebInputEventResult GestureManager::handleGestureShowPress()
284 {
285 m_lastShowPressTimestamp = WTF::monotonicallyIncreasingTime();
286
287 FrameView* view = m_frame->view();
288 if (!view)
289 return WebInputEventResult::NotHandled;
290 if (ScrollAnimatorBase* scrollAnimator = view->existingScrollAnimator())
291 scrollAnimator->cancelAnimation();
292 const FrameView::ScrollableAreaSet* areas = view->scrollableAreas();
293 if (!areas)
294 return WebInputEventResult::NotHandled;
295 for (const ScrollableArea* scrollableArea : *areas) {
296 ScrollAnimatorBase* animator = scrollableArea->existingScrollAnimator();
297 if (animator)
298 animator->cancelAnimation();
299 }
300 return WebInputEventResult::NotHandled;
301 }
302
303 FrameHost* GestureManager::frameHost() const
304 {
305 if (!m_frame->page())
306 return nullptr;
307
308 return &m_frame->page()->frameHost();
309 }
310
311 double GestureManager::getLastShowPressTimestamp() const
312 {
313 return m_lastShowPressTimestamp;
314 }
315
316 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/GestureManager.h ('k') | third_party/WebKit/Source/core/input/KeyboardEventManager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698