OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include "sky/engine/config.h" | 28 #include "sky/engine/config.h" |
29 #include "sky/engine/core/page/EventHandler.h" | 29 #include "sky/engine/core/page/EventHandler.h" |
30 | 30 |
31 #include "gen/sky/core/HTMLNames.h" | 31 #include "gen/sky/core/HTMLNames.h" |
32 #include "gen/sky/platform/RuntimeEnabledFeatures.h" | 32 #include "gen/sky/platform/RuntimeEnabledFeatures.h" |
33 #include "sky/engine/bindings/core/v8/ExceptionStatePlaceholder.h" | 33 #include "sky/engine/bindings/core/v8/ExceptionStatePlaceholder.h" |
34 #include "sky/engine/core/dom/Document.h" | 34 #include "sky/engine/core/dom/Document.h" |
35 #include "sky/engine/core/dom/DocumentMarkerController.h" | 35 #include "sky/engine/core/dom/DocumentMarkerController.h" |
36 #include "sky/engine/core/dom/NodeRenderingTraversal.h" | 36 #include "sky/engine/core/dom/NodeRenderingTraversal.h" |
37 #include "sky/engine/core/dom/TouchList.h" | |
38 #include "sky/engine/core/dom/shadow/ShadowRoot.h" | 37 #include "sky/engine/core/dom/shadow/ShadowRoot.h" |
39 #include "sky/engine/core/editing/Editor.h" | 38 #include "sky/engine/core/editing/Editor.h" |
40 #include "sky/engine/core/editing/FrameSelection.h" | 39 #include "sky/engine/core/editing/FrameSelection.h" |
41 #include "sky/engine/core/editing/TextIterator.h" | 40 #include "sky/engine/core/editing/TextIterator.h" |
42 #include "sky/engine/core/editing/htmlediting.h" | 41 #include "sky/engine/core/editing/htmlediting.h" |
43 #include "sky/engine/core/events/DOMWindowEventQueue.h" | 42 #include "sky/engine/core/events/DOMWindowEventQueue.h" |
44 #include "sky/engine/core/events/EventPath.h" | 43 #include "sky/engine/core/events/EventPath.h" |
45 #include "sky/engine/core/events/KeyboardEvent.h" | 44 #include "sky/engine/core/events/KeyboardEvent.h" |
46 #include "sky/engine/core/events/TextEvent.h" | 45 #include "sky/engine/core/events/TextEvent.h" |
47 #include "sky/engine/core/events/TouchEvent.h" | |
48 #include "sky/engine/core/fetch/ImageResource.h" | 46 #include "sky/engine/core/fetch/ImageResource.h" |
49 #include "sky/engine/core/frame/FrameView.h" | 47 #include "sky/engine/core/frame/FrameView.h" |
50 #include "sky/engine/core/frame/LocalFrame.h" | 48 #include "sky/engine/core/frame/LocalFrame.h" |
51 #include "sky/engine/core/frame/Settings.h" | 49 #include "sky/engine/core/frame/Settings.h" |
52 #include "sky/engine/core/loader/FrameLoaderClient.h" | 50 #include "sky/engine/core/loader/FrameLoaderClient.h" |
53 #include "sky/engine/core/page/AutoscrollController.h" | 51 #include "sky/engine/core/page/AutoscrollController.h" |
54 #include "sky/engine/core/page/Chrome.h" | 52 #include "sky/engine/core/page/Chrome.h" |
55 #include "sky/engine/core/page/ChromeClient.h" | 53 #include "sky/engine/core/page/ChromeClient.h" |
56 #include "sky/engine/core/page/EditorClient.h" | 54 #include "sky/engine/core/page/EditorClient.h" |
57 #include "sky/engine/core/page/EventWithHitTestResults.h" | 55 #include "sky/engine/core/page/EventWithHitTestResults.h" |
58 #include "sky/engine/core/page/FocusController.h" | 56 #include "sky/engine/core/page/FocusController.h" |
59 #include "sky/engine/core/page/Page.h" | 57 #include "sky/engine/core/page/Page.h" |
60 #include "sky/engine/core/rendering/HitTestRequest.h" | 58 #include "sky/engine/core/rendering/HitTestRequest.h" |
61 #include "sky/engine/core/rendering/HitTestResult.h" | 59 #include "sky/engine/core/rendering/HitTestResult.h" |
62 #include "sky/engine/core/rendering/RenderLayer.h" | 60 #include "sky/engine/core/rendering/RenderLayer.h" |
63 #include "sky/engine/core/rendering/RenderView.h" | 61 #include "sky/engine/core/rendering/RenderView.h" |
64 #include "sky/engine/core/rendering/style/RenderStyle.h" | 62 #include "sky/engine/core/rendering/style/RenderStyle.h" |
65 #include "sky/engine/platform/PlatformGestureEvent.h" | 63 #include "sky/engine/platform/PlatformGestureEvent.h" |
66 #include "sky/engine/platform/PlatformKeyboardEvent.h" | 64 #include "sky/engine/platform/PlatformKeyboardEvent.h" |
67 #include "sky/engine/platform/PlatformTouchEvent.h" | |
68 #include "sky/engine/platform/TraceEvent.h" | 65 #include "sky/engine/platform/TraceEvent.h" |
69 #include "sky/engine/platform/WindowsKeyboardCodes.h" | 66 #include "sky/engine/platform/WindowsKeyboardCodes.h" |
70 #include "sky/engine/platform/geometry/FloatPoint.h" | 67 #include "sky/engine/platform/geometry/FloatPoint.h" |
71 #include "sky/engine/platform/graphics/Image.h" | 68 #include "sky/engine/platform/graphics/Image.h" |
72 #include "sky/engine/platform/heap/Handle.h" | 69 #include "sky/engine/platform/heap/Handle.h" |
73 #include "sky/engine/platform/scroll/ScrollAnimator.h" | 70 #include "sky/engine/platform/scroll/ScrollAnimator.h" |
74 #include "sky/engine/platform/scroll/Scrollbar.h" | 71 #include "sky/engine/platform/scroll/Scrollbar.h" |
75 #include "sky/engine/wtf/Assertions.h" | 72 #include "sky/engine/wtf/Assertions.h" |
76 #include "sky/engine/wtf/CurrentTime.h" | 73 #include "sky/engine/wtf/CurrentTime.h" |
77 #include "sky/engine/wtf/StdLibExtras.h" | 74 #include "sky/engine/wtf/StdLibExtras.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 , m_capturesDragging(false) | 130 , m_capturesDragging(false) |
134 , m_mouseDownMayStartSelect(false) | 131 , m_mouseDownMayStartSelect(false) |
135 , m_mouseDownMayStartDrag(false) | 132 , m_mouseDownMayStartDrag(false) |
136 , m_selectionInitiationState(HaveNotStartedSelection) | 133 , m_selectionInitiationState(HaveNotStartedSelection) |
137 , m_hoverTimer(this, &EventHandler::hoverTimerFired) | 134 , m_hoverTimer(this, &EventHandler::hoverTimerFired) |
138 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) | 135 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) |
139 , m_mouseDownMayStartAutoscroll(false) | 136 , m_mouseDownMayStartAutoscroll(false) |
140 , m_clickCount(0) | 137 , m_clickCount(0) |
141 , m_shouldOnlyFireDragOverEvent(false) | 138 , m_shouldOnlyFireDragOverEvent(false) |
142 , m_mousePositionIsUnknown(true) | 139 , m_mousePositionIsUnknown(true) |
143 , m_touchPressed(false) | |
144 , m_scrollGestureHandlingNode(nullptr) | 140 , m_scrollGestureHandlingNode(nullptr) |
145 , m_lastGestureScrollOverWidget(false) | 141 , m_lastGestureScrollOverWidget(false) |
146 , m_maxMouseMovedDuration(0) | 142 , m_maxMouseMovedDuration(0) |
147 , m_didStartDrag(false) | 143 , m_didStartDrag(false) |
148 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) | 144 , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) |
149 , m_lastShowPressTimestamp(0) | 145 , m_lastShowPressTimestamp(0) |
150 { | 146 { |
151 } | 147 } |
152 | 148 |
153 EventHandler::~EventHandler() | 149 EventHandler::~EventHandler() |
(...skipping 12 matching lines...) Expand all Loading... |
166 m_clickNode = nullptr; | 162 m_clickNode = nullptr; |
167 m_dragTarget = nullptr; | 163 m_dragTarget = nullptr; |
168 m_shouldOnlyFireDragOverEvent = false; | 164 m_shouldOnlyFireDragOverEvent = false; |
169 m_mousePositionIsUnknown = true; | 165 m_mousePositionIsUnknown = true; |
170 m_lastKnownMousePosition = IntPoint(); | 166 m_lastKnownMousePosition = IntPoint(); |
171 m_lastKnownMouseGlobalPosition = IntPoint(); | 167 m_lastKnownMouseGlobalPosition = IntPoint(); |
172 m_mousePressNode = nullptr; | 168 m_mousePressNode = nullptr; |
173 m_mousePressed = false; | 169 m_mousePressed = false; |
174 m_capturesDragging = false; | 170 m_capturesDragging = false; |
175 m_previousWheelScrolledNode = nullptr; | 171 m_previousWheelScrolledNode = nullptr; |
176 m_targetForTouchID.clear(); | |
177 m_touchSequenceDocument.clear(); | |
178 m_scrollGestureHandlingNode = nullptr; | 172 m_scrollGestureHandlingNode = nullptr; |
179 m_lastGestureScrollOverWidget = false; | 173 m_lastGestureScrollOverWidget = false; |
180 m_previousGestureScrolledNode = nullptr; | 174 m_previousGestureScrolledNode = nullptr; |
181 m_scrollbarHandlingScrollGesture = nullptr; | 175 m_scrollbarHandlingScrollGesture = nullptr; |
182 m_maxMouseMovedDuration = 0; | 176 m_maxMouseMovedDuration = 0; |
183 m_didStartDrag = false; | 177 m_didStartDrag = false; |
184 m_touchPressed = false; | |
185 m_mouseDownMayStartSelect = false; | 178 m_mouseDownMayStartSelect = false; |
186 m_mouseDownMayStartDrag = false; | 179 m_mouseDownMayStartDrag = false; |
187 m_lastShowPressTimestamp = 0; | 180 m_lastShowPressTimestamp = 0; |
188 m_lastDeferredTapElement = nullptr; | 181 m_lastDeferredTapElement = nullptr; |
189 } | 182 } |
190 | 183 |
191 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) | 184 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
192 { | 185 { |
193 if (!nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) | 186 if (!nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) |
194 return; | 187 return; |
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 } | 820 } |
828 | 821 |
829 bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults&
targetedEvent) | 822 bool EventHandler::handleGestureLongPress(const GestureEventWithHitTestResults&
targetedEvent) |
830 { | 823 { |
831 const PlatformGestureEvent& gestureEvent = targetedEvent.event(); | 824 const PlatformGestureEvent& gestureEvent = targetedEvent.event(); |
832 | 825 |
833 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests
here (re-using the | 826 // FIXME: Ideally we should try to remove the extra mouse-specific hit-tests
here (re-using the |
834 // supplied HitTestResult), but that will require some overhaul of the touch
drag-and-drop code | 827 // supplied HitTestResult), but that will require some overhaul of the touch
drag-and-drop code |
835 // and LongPress is such a special scenario that it's unlikely to matter muc
h in practice. | 828 // and LongPress is such a special scenario that it's unlikely to matter muc
h in practice. |
836 | 829 |
837 #if OS(ANDROID) | 830 IntPoint hitTestPoint = gestureEvent.position(); |
838 bool shouldLongPressSelectWord = true; | 831 HitTestResult result = hitTestResultAtPoint(hitTestPoint); |
839 #else | 832 Node* innerNode = result.targetNode(); |
840 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()-
>touchEditingEnabled(); | 833 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() ||
innerNode->isTextNode())) { |
841 #endif | 834 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitespace)
; |
842 if (shouldLongPressSelectWord) { | 835 if (m_frame->selection().isRange()) { |
843 IntPoint hitTestPoint = gestureEvent.position(); | 836 focusDocumentView(); |
844 HitTestResult result = hitTestResultAtPoint(hitTestPoint); | 837 return true; |
845 Node* innerNode = result.targetNode(); | |
846 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable()
|| innerNode->isTextNode())) { | |
847 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitesp
ace); | |
848 if (m_frame->selection().isRange()) { | |
849 focusDocumentView(); | |
850 return true; | |
851 } | |
852 } | 838 } |
853 } | 839 } |
| 840 |
854 return true; | 841 return true; |
855 } | 842 } |
856 | 843 |
857 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) | 844 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) |
858 { | 845 { |
859 return false; | 846 return false; |
860 } | 847 } |
861 | 848 |
862 bool EventHandler::passScrollGestureEventToWidget(const PlatformGestureEvent& ge
stureEvent, RenderObject* renderer) | 849 bool EventHandler::passScrollGestureEventToWidget(const PlatformGestureEvent& ge
stureEvent, RenderObject* renderer) |
863 { | 850 { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 if (shouldKeepActiveForMinInterval) { | 987 if (shouldKeepActiveForMinInterval) { |
1001 m_lastDeferredTapElement = hitTestResult.innerElement(); | 988 m_lastDeferredTapElement = hitTestResult.innerElement(); |
1002 m_activeIntervalTimer.startOneShot(minimumActiveInterval - activeInterva
l, FROM_HERE); | 989 m_activeIntervalTimer.startOneShot(minimumActiveInterval - activeInterva
l, FROM_HERE); |
1003 } | 990 } |
1004 | 991 |
1005 return GestureEventWithHitTestResults(gestureEvent, hitTestResult); | 992 return GestureEventWithHitTestResults(gestureEvent, hitTestResult); |
1006 } | 993 } |
1007 | 994 |
1008 HitTestRequest::HitTestRequestType EventHandler::getHitTypeForGestureType(Platfo
rmEvent::Type type) | 995 HitTestRequest::HitTestRequestType EventHandler::getHitTypeForGestureType(Platfo
rmEvent::Type type) |
1009 { | 996 { |
1010 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent; | 997 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly; |
1011 switch (type) { | 998 switch (type) { |
1012 case PlatformEvent::GestureShowPress: | 999 case PlatformEvent::GestureShowPress: |
1013 case PlatformEvent::GestureTapUnconfirmed: | 1000 case PlatformEvent::GestureTapUnconfirmed: |
1014 return hitType | HitTestRequest::Active; | 1001 return hitType | HitTestRequest::Active; |
1015 case PlatformEvent::GestureTapDownCancel: | 1002 case PlatformEvent::GestureTapDownCancel: |
1016 // A TapDownCancel received when no element is active shouldn't really b
e changing hover state. | 1003 // A TapDownCancel received when no element is active shouldn't really b
e changing hover state. |
1017 if (!m_frame->document()->activeHoverElement()) | 1004 if (!m_frame->document()->activeHoverElement()) |
1018 hitType |= HitTestRequest::ReadOnly; | 1005 hitType |= HitTestRequest::ReadOnly; |
1019 return hitType | HitTestRequest::Release; | 1006 return hitType | HitTestRequest::Release; |
1020 case PlatformEvent::GestureTap: | 1007 case PlatformEvent::GestureTap: |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1220 m_lastScrollbarUnderMouse->mouseExited(); | 1207 m_lastScrollbarUnderMouse->mouseExited(); |
1221 | 1208 |
1222 // Send mouse entered if we're setting a new scrollbar. | 1209 // Send mouse entered if we're setting a new scrollbar. |
1223 if (scrollbar && setLast) | 1210 if (scrollbar && setLast) |
1224 scrollbar->mouseEntered(); | 1211 scrollbar->mouseEntered(); |
1225 | 1212 |
1226 m_lastScrollbarUnderMouse = setLast ? scrollbar : 0; | 1213 m_lastScrollbarUnderMouse = setLast ? scrollbar : 0; |
1227 } | 1214 } |
1228 } | 1215 } |
1229 | 1216 |
1230 static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State
state) | |
1231 { | |
1232 switch (state) { | |
1233 case PlatformTouchPoint::TouchReleased: | |
1234 return EventTypeNames::touchend; | |
1235 case PlatformTouchPoint::TouchCancelled: | |
1236 return EventTypeNames::touchcancel; | |
1237 case PlatformTouchPoint::TouchPressed: | |
1238 return EventTypeNames::touchstart; | |
1239 case PlatformTouchPoint::TouchMoved: | |
1240 return EventTypeNames::touchmove; | |
1241 case PlatformTouchPoint::TouchStationary: | |
1242 // TouchStationary state is not converted to touch events, so fall throu
gh to assert. | |
1243 default: | |
1244 ASSERT_NOT_REACHED(); | |
1245 return emptyAtom; | |
1246 } | |
1247 } | |
1248 | |
1249 HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const Layout
Point& point, HitTestRequest::HitTestRequestType hitType) | 1217 HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const Layout
Point& point, HitTestRequest::HitTestRequestType hitType) |
1250 { | 1218 { |
1251 HitTestResult result(point); | 1219 HitTestResult result(point); |
1252 | 1220 |
1253 if (!frame || !frame->contentRenderer()) | 1221 if (!frame || !frame->contentRenderer()) |
1254 return result; | 1222 return result; |
1255 if (frame->view()) { | 1223 if (frame->view()) { |
1256 IntRect rect = frame->view()->visibleContentRect(); | 1224 IntRect rect = frame->view()->visibleContentRect(); |
1257 if (!rect.contains(roundedIntPoint(point))) | 1225 if (!rect.contains(roundedIntPoint(point))) |
1258 return result; | 1226 return result; |
1259 } | 1227 } |
1260 frame->contentRenderer()->hitTest(HitTestRequest(hitType), result); | 1228 frame->contentRenderer()->hitTest(HitTestRequest(hitType), result); |
1261 return result; | 1229 return result; |
1262 } | 1230 } |
1263 | 1231 |
1264 bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) | |
1265 { | |
1266 TRACE_EVENT0("blink", "EventHandler::handleTouchEvent"); | |
1267 | |
1268 const Vector<PlatformTouchPoint>& points = event.touchPoints(); | |
1269 | |
1270 unsigned i; | |
1271 bool freshTouchEvents = true; | |
1272 bool allTouchReleased = true; | |
1273 for (i = 0; i < points.size(); ++i) { | |
1274 const PlatformTouchPoint& point = points[i]; | |
1275 if (point.state() != PlatformTouchPoint::TouchPressed) | |
1276 freshTouchEvents = false; | |
1277 if (point.state() != PlatformTouchPoint::TouchReleased && point.state()
!= PlatformTouchPoint::TouchCancelled) | |
1278 allTouchReleased = false; | |
1279 } | |
1280 if (freshTouchEvents) { | |
1281 // Ideally we'd ASSERT !m_touchSequenceDocument here since we should | |
1282 // have cleared the active document when we saw the last release. But we | |
1283 // have some tests that violate this, ClusterFuzz could trigger it, and | |
1284 // there may be cases where the browser doesn't reliably release all | |
1285 // touches. http://crbug.com/345372 tracks this. | |
1286 m_touchSequenceDocument.clear(); | |
1287 } | |
1288 | |
1289 ASSERT(m_frame->view()); | |
1290 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touc
hSequenceDocument->frame()->view())) { | |
1291 // If the active touch document has no frame or view, it's probably bein
g destroyed | |
1292 // so we can't dispatch events. | |
1293 return false; | |
1294 } | |
1295 | |
1296 // First do hit tests for any new touch points. | |
1297 for (i = 0; i < points.size(); ++i) { | |
1298 const PlatformTouchPoint& point = points[i]; | |
1299 | |
1300 // Touch events implicitly capture to the touched node, and don't change | |
1301 // active/hover states themselves (Gesture events do). So we only need | |
1302 // to hit-test on touchstart, and it can be read-only. | |
1303 if (point.state() == PlatformTouchPoint::TouchPressed) { | |
1304 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEv
ent | HitTestRequest::ReadOnly | HitTestRequest::Active; | |
1305 LayoutPoint pagePoint = roundedLayoutPoint(point.pos()); | |
1306 HitTestResult result; | |
1307 if (!m_touchSequenceDocument) { | |
1308 result = hitTestResultAtPoint(pagePoint, hitType); | |
1309 } else if (m_touchSequenceDocument->frame()) { | |
1310 LayoutPoint framePoint = roundedLayoutPoint(point.pos()); | |
1311 result = hitTestResultInFrame(m_touchSequenceDocument->frame(),
framePoint, hitType); | |
1312 } else | |
1313 continue; | |
1314 | |
1315 Node* node = result.innerNode(); | |
1316 if (!node) | |
1317 continue; | |
1318 | |
1319 // Touch events should not go to text nodes | |
1320 if (node->isTextNode()) | |
1321 node = NodeRenderingTraversal::parent(node); | |
1322 | |
1323 if (!m_touchSequenceDocument) { | |
1324 // Keep track of which document should receive all touch events | |
1325 // in the active sequence. This must be a single document to | |
1326 // ensure we don't leak Nodes between documents. | |
1327 m_touchSequenceDocument = &(result.innerNode()->document()); | |
1328 ASSERT(m_touchSequenceDocument->frame()->view()); | |
1329 } | |
1330 | |
1331 // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) | |
1332 // since we shouldn't get a touchstart for a touch that's already | |
1333 // down. However EventSender allows this to be violated and there's | |
1334 // some tests that take advantage of it. There may also be edge | |
1335 // cases in the browser where this happens. | |
1336 // See http://crbug.com/345372. | |
1337 m_targetForTouchID.set(point.id(), node); | |
1338 | |
1339 TouchAction effectiveTouchAction = computeEffectiveTouchAction(*node
); | |
1340 if (effectiveTouchAction != TouchActionAuto) | |
1341 m_frame->page()->chrome().client().setTouchAction(effectiveTouch
Action); | |
1342 } | |
1343 } | |
1344 | |
1345 m_touchPressed = !allTouchReleased; | |
1346 | |
1347 // If there's no document receiving touch events, then we can skip all the | |
1348 // rest of this work. | |
1349 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frame()) { | |
1350 if (allTouchReleased) | |
1351 m_touchSequenceDocument.clear(); | |
1352 return false; | |
1353 } | |
1354 | |
1355 // Build up the lists to use for the 'touches', 'targetTouches' and | |
1356 // 'changedTouches' attributes in the JS event. See | |
1357 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these | |
1358 // lists fit together. | |
1359 | |
1360 // Holds the complete set of touches on the screen. | |
1361 RefPtr<TouchList> touches = TouchList::create(); | |
1362 | |
1363 // A different view on the 'touches' list above, filtered and grouped by | |
1364 // event target. Used for the 'targetTouches' list in the JS event. | |
1365 typedef HashMap<EventTarget*, RefPtr<TouchList> > TargetTouchesHeapMap; | |
1366 TargetTouchesHeapMap touchesByTarget; | |
1367 | |
1368 // Array of touches per state, used to assemble the 'changedTouches' list. | |
1369 typedef HashSet<RefPtr<EventTarget> > EventTargetSet; | |
1370 struct { | |
1371 // The touches corresponding to the particular change state this struct | |
1372 // instance represents. | |
1373 RefPtr<TouchList> m_touches; | |
1374 // Set of targets involved in m_touches. | |
1375 EventTargetSet m_targets; | |
1376 } changedTouches[PlatformTouchPoint::TouchStateEnd]; | |
1377 | |
1378 for (i = 0; i < points.size(); ++i) { | |
1379 const PlatformTouchPoint& point = points[i]; | |
1380 PlatformTouchPoint::State pointState = point.state(); | |
1381 RefPtr<EventTarget> touchTarget = nullptr; | |
1382 | |
1383 if (pointState == PlatformTouchPoint::TouchReleased || pointState == Pla
tformTouchPoint::TouchCancelled) { | |
1384 // The target should be the original target for this touch, so get | |
1385 // it from the hashmap. As it's a release or cancel we also remove | |
1386 // it from the map. | |
1387 touchTarget = m_targetForTouchID.take(point.id()); | |
1388 } else { | |
1389 // No hittest is performed on move or stationary, since the target | |
1390 // is not allowed to change anyway. | |
1391 touchTarget = m_targetForTouchID.get(point.id()); | |
1392 } | |
1393 | |
1394 LocalFrame* targetFrame = 0; | |
1395 bool knownTarget = false; | |
1396 if (touchTarget) { | |
1397 Document& doc = touchTarget->toNode()->document(); | |
1398 // If the target node has moved to a new document while it was being
touched, | |
1399 // we can't send events to the new document because that could leak
nodes | |
1400 // from one document to another. See http://crbug.com/394339. | |
1401 if (&doc == m_touchSequenceDocument.get()) { | |
1402 targetFrame = doc.frame(); | |
1403 knownTarget = true; | |
1404 } | |
1405 } | |
1406 if (!knownTarget) { | |
1407 // If we don't have a target registered for the point it means we've | |
1408 // missed our opportunity to do a hit test for it (due to some | |
1409 // optimization that prevented blink from ever seeing the | |
1410 // touchstart), or that the touch started outside the active touch | |
1411 // sequence document. We should still include the touch in the | |
1412 // Touches list reported to the application (eg. so it can | |
1413 // differentiate between a one and two finger gesture), but we won't | |
1414 // actually dispatch any events for it. Set the target to the | |
1415 // Document so that there's some valid node here. Perhaps this | |
1416 // should really be LocalDOMWindow, but in all other cases the targe
t of | |
1417 // a Touch is a Node so using the window could be a breaking change. | |
1418 // Since we know there was no handler invoked, the specific target | |
1419 // should be completely irrelevant to the application. | |
1420 touchTarget = m_touchSequenceDocument; | |
1421 targetFrame = m_touchSequenceDocument->frame(); | |
1422 } | |
1423 ASSERT(targetFrame); | |
1424 | |
1425 RefPtr<Touch> touch = Touch::create( | |
1426 targetFrame, touchTarget.get(), point.id(), point.screenPos(), point
.pos(), point.radius(), point.rotationAngle(), point.force()); | |
1427 | |
1428 // Ensure this target's touch list exists, even if it ends up empty, so | |
1429 // it can always be passed to TouchEvent::Create below. | |
1430 TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.f
ind(touchTarget.get()); | |
1431 if (targetTouchesIterator == touchesByTarget.end()) { | |
1432 touchesByTarget.set(touchTarget.get(), TouchList::create()); | |
1433 targetTouchesIterator = touchesByTarget.find(touchTarget.get()); | |
1434 } | |
1435 | |
1436 // touches and targetTouches should only contain information about | |
1437 // touches still on the screen, so if this point is released or | |
1438 // cancelled it will only appear in the changedTouches list. | |
1439 if (pointState != PlatformTouchPoint::TouchReleased && pointState != Pla
tformTouchPoint::TouchCancelled) { | |
1440 touches->append(touch); | |
1441 targetTouchesIterator->value->append(touch); | |
1442 } | |
1443 | |
1444 // Now build up the correct list for changedTouches. | |
1445 // Note that any touches that are in the TouchStationary state (e.g. if | |
1446 // the user had several points touched but did not move them all) should | |
1447 // never be in the changedTouches list so we do not handle them | |
1448 // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609 | |
1449 // for further discussion about the TouchStationary state. | |
1450 if (pointState != PlatformTouchPoint::TouchStationary && knownTarget) { | |
1451 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); | |
1452 if (!changedTouches[pointState].m_touches) | |
1453 changedTouches[pointState].m_touches = TouchList::create(); | |
1454 changedTouches[pointState].m_touches->append(touch); | |
1455 changedTouches[pointState].m_targets.add(touchTarget); | |
1456 } | |
1457 } | |
1458 if (allTouchReleased) | |
1459 m_touchSequenceDocument.clear(); | |
1460 | |
1461 // Now iterate the changedTouches list and m_targets within it, sending | |
1462 // events to the targets as required. | |
1463 bool swallowedEvent = false; | |
1464 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state
) { | |
1465 if (!changedTouches[state].m_touches) | |
1466 continue; | |
1467 | |
1468 const AtomicString& stateName(eventNameForTouchPointState(static_cast<Pl
atformTouchPoint::State>(state))); | |
1469 const EventTargetSet& targetsForState = changedTouches[state].m_targets; | |
1470 for (EventTargetSet::const_iterator it = targetsForState.begin(); it !=
targetsForState.end(); ++it) { | |
1471 EventTarget* touchEventTarget = it->get(); | |
1472 RefPtr<TouchEvent> touchEvent = TouchEvent::create( | |
1473 touches.get(), touchesByTarget.get(touchEventTarget), changedTou
ches[state].m_touches.get(), | |
1474 stateName, touchEventTarget->toNode()->document().domWindow(), | |
1475 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey
(), event.cancelable()); | |
1476 touchEventTarget->toNode()->dispatchTouchEvent(touchEvent.get()); | |
1477 swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() ||
touchEvent->defaultHandled(); | |
1478 } | |
1479 } | |
1480 | |
1481 return swallowedEvent; | |
1482 } | |
1483 | |
1484 TouchAction EventHandler::intersectTouchAction(TouchAction action1, TouchAction
action2) | 1232 TouchAction EventHandler::intersectTouchAction(TouchAction action1, TouchAction
action2) |
1485 { | 1233 { |
1486 if (action1 == TouchActionNone || action2 == TouchActionNone) | 1234 if (action1 == TouchActionNone || action2 == TouchActionNone) |
1487 return TouchActionNone; | 1235 return TouchActionNone; |
1488 if (action1 == TouchActionAuto) | 1236 if (action1 == TouchActionAuto) |
1489 return action2; | 1237 return action2; |
1490 if (action2 == TouchActionAuto) | 1238 if (action2 == TouchActionAuto) |
1491 return action1; | 1239 return action1; |
1492 if (!(action1 & action2)) | 1240 if (!(action1 & action2)) |
1493 return TouchActionNone; | 1241 return TouchActionNone; |
(...skipping 25 matching lines...) Expand all Loading... |
1519 | 1267 |
1520 void EventHandler::focusDocumentView() | 1268 void EventHandler::focusDocumentView() |
1521 { | 1269 { |
1522 Page* page = m_frame->page(); | 1270 Page* page = m_frame->page(); |
1523 if (!page) | 1271 if (!page) |
1524 return; | 1272 return; |
1525 page->focusController().focusDocumentView(m_frame); | 1273 page->focusController().focusDocumentView(m_frame); |
1526 } | 1274 } |
1527 | 1275 |
1528 } // namespace blink | 1276 } // namespace blink |
OLD | NEW |