Changeset 167698 in webkit
- Timestamp:
- Apr 22, 2014 10:53:05 PM (10 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r167690 r167698 1 2014-04-22 Benjamin Poulain <bpoulain@apple.com> 2 3 [iOS][WK2] Split iOS touch event dispatch for the regular touch event dispatch 4 https://bugs.webkit.org/show_bug.cgi?id=132033 5 6 Reviewed by Simon Fraser. 7 8 The generic touch event dispatching does not work well with iOS gesture recognizers. 9 Some events are required to be synchronous, while other needs can be asynchronous and 10 can even use event coalescing. We only need UI callback for the synchronous events. 11 12 Previously, that was implemented by changing the property ShouldSendEventsSynchronously 13 on WebPageProxy. That is causing issues when synchronous events are sent right after asynchronous 14 events because the responses in WebPageProxy::didReceiveEvent() easily get out of order. 15 16 This patch completely split the UIGestureRecognizerDispatching from the normal asynchronous event dispatching. 17 18 Synchronous events are sent directly to the WebProcess and report the result to the PageClient right away. 19 20 Asynchronous events are sent to the EventDispatcher where they are coalesced until the main thread is free 21 to process events. 22 23 There can be a race where a synchronous event comes before the asynchronous events are processed. In that case, 24 the synchronous event handler starts by getting the events out of the EventDispatcher and dispatch them first. 25 26 * Shared/NativeWebTouchEvent.h: 27 (WebKit::NativeWebTouchEvent::uniqueId): Deleted. 28 * Shared/ios/NativeWebTouchEventIOS.mm: 29 (WebKit::NativeWebTouchEvent::NativeWebTouchEvent): 30 * UIProcess/WebPageProxy.cpp: 31 (WebKit::WebPageProxy::handleSynchronousTouchEvent): 32 (WebKit::WebPageProxy::sendAsynchronousTouchEvent): 33 (WebKit::WebPageProxy::didReceiveEvent): 34 (WebKit::WebPageProxy::resetStateAfterProcessExited): 35 * UIProcess/WebPageProxy.h: 36 * UIProcess/ios/WKContentViewInteraction.h: 37 * UIProcess/ios/WKContentViewInteraction.mm: 38 (-[WKContentView _webTouchEventsRecognized:]): 39 (-[WKContentView _webTouchEvent:WebKit::preventsNativeGestures:]): 40 * WebProcess/WebPage/EventDispatcher.cpp: 41 (WebKit::EventDispatcher::EventDispatcher): 42 (WebKit::EventDispatcher::clearQueuedTouchEventsForPage): 43 (WebKit::EventDispatcher::getQueuedTouchEventsForPage): 44 (WebKit::EventDispatcher::touchEvent): 45 (WebKit::EventDispatcher::dispatchTouchEvents): 46 * WebProcess/WebPage/EventDispatcher.h: 47 * WebProcess/WebPage/EventDispatcher.messages.in: 48 * WebProcess/WebPage/WebPage.cpp: 49 (WebKit::WebPage::dispatchTouchEvent): 50 (WebKit::WebPage::touchEventSync): 51 (WebKit::WebPage::touchEvent): 52 (WebKit::WebPage::touchEventSyncForTesting): 53 (WebKit::WebPage::didCommitLoad): 54 * WebProcess/WebPage/WebPage.h: 55 * WebProcess/WebPage/WebPage.messages.in: 56 * WebProcess/WebPage/ios/WebPageIOS.mm: 57 (WebKit::WebPage::dispatchAsynchronousTouchEventsQueue): 58 1 59 2014-04-22 Chris Fleizach <cfleizach@apple.com> 2 60 -
trunk/Source/WebKit2/Shared/NativeWebTouchEvent.h
r164776 r167698 49 49 #if PLATFORM(IOS) 50 50 explicit NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *); 51 unsigned uniqueId() const { return m_uniqueID; }52 51 #elif PLATFORM(GTK) 53 52 NativeWebTouchEvent(const NativeWebTouchEvent&); … … 61 60 62 61 private: 63 #if PLATFORM(IOS) 64 unsigned m_uniqueID; 65 #elif PLATFORM(GTK) 62 #if PLATFORM(GTK) 66 63 GUniquePtr<GdkEvent> m_nativeEvent; 67 64 const WebCore::GtkTouchContextHelper& m_touchContext; -
trunk/Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm
r164776 r167698 37 37 38 38 namespace WebKit { 39 40 static unsigned uniqueTouchEventIdIndex = 0;41 39 42 40 static inline WebEvent::Type webEventTypeForUIWebTouchEventType(UIWebTouchEventType type) … … 100 98 NativeWebTouchEvent::NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *gestureRecognizer) 101 99 : WebTouchEvent(webEventTypeForUIWebTouchEventType(gestureRecognizer.type), static_cast<Modifiers>(0), WTF::currentTime(), extractWebTouchPoint(gestureRecognizer), positionForCGPoint(gestureRecognizer.locationInWindow), gestureRecognizer.inJavaScriptGesture, gestureRecognizer.scale, gestureRecognizer.rotation) 102 , m_uniqueID(uniqueTouchEventIdIndex++)103 100 { 104 101 } -
trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp
r167686 r167698 1494 1494 return true; 1495 1495 } 1496 1496 #endif 1497 1498 #if ENABLE(IOS_TOUCH_EVENTS) 1499 void WebPageProxy::handleTouchEventSynchronously(const NativeWebTouchEvent& event) 1500 { 1501 if (!isValid()) 1502 return; 1503 1504 if (event.type() == WebEvent::TouchStart) 1505 m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event); 1506 1507 if (!m_isTrackingTouchEvents) 1508 return; 1509 1510 m_process->responsivenessTimer()->start(); 1511 bool handled = false; 1512 m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID); 1513 didReceiveEvent(event.type(), handled); 1514 m_pageClient.doneWithTouchEvent(event, handled); 1515 m_process->responsivenessTimer()->stop(); 1516 1517 if (event.type() == WebEvent::TouchEnd || event.type() == WebEvent::TouchCancel) 1518 m_isTrackingTouchEvents = false; 1519 } 1520 1521 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event) 1522 { 1523 if (!isValid()) 1524 return; 1525 1526 ASSERT(event.type() != WebEvent::TouchStart); 1527 1528 if (!m_isTrackingTouchEvents) 1529 return; 1530 1531 m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0); 1532 1533 if (event.type() == WebEvent::TouchEnd || event.type() == WebEvent::TouchCancel) 1534 m_isTrackingTouchEvents = false; 1535 } 1536 1537 #elif ENABLE(TOUCH_EVENTS) 1497 1538 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event) 1498 1539 { … … 3798 3839 break; 3799 3840 } 3800 #if ENABLE(TOUCH_EVENTS) 3841 #if ENABLE(IOS_TOUCH_EVENTS) 3842 case WebEvent::TouchStart: 3843 case WebEvent::TouchMove: 3844 case WebEvent::TouchEnd: 3845 case WebEvent::TouchCancel: 3846 break; 3847 #elif ENABLE(TOUCH_EVENTS) 3801 3848 case WebEvent::TouchStart: 3802 3849 case WebEvent::TouchMove: … … 4154 4201 m_processingMouseMoveEvent = false; 4155 4202 4156 #if ENABLE(TOUCH_EVENTS) 4203 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS) 4157 4204 m_touchEventQueue.clear(); 4158 4205 #endif -
trunk/Source/WebKit2/UIProcess/WebPageProxy.h
r167686 r167698 695 695 void handleWheelEvent(const NativeWebWheelEvent&); 696 696 void handleKeyboardEvent(const NativeWebKeyboardEvent&); 697 #if ENABLE(TOUCH_EVENTS) 697 #if ENABLE(IOS_TOUCH_EVENTS) 698 void handleTouchEventSynchronously(const NativeWebTouchEvent&); 699 void handleTouchEventAsynchronously(const NativeWebTouchEvent&); 700 #elif ENABLE(TOUCH_EVENTS) 698 701 void handleTouchEvent(const NativeWebTouchEvent&); 699 702 #endif … … 1564 1567 #if ENABLE(TOUCH_EVENTS) 1565 1568 bool m_isTrackingTouchEvents; 1569 #endif 1570 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS) 1566 1571 Deque<QueuedTouchEvents> m_touchEventQueue; 1567 1572 #endif 1573 1568 1574 #if ENABLE(INPUT_TYPE_COLOR) 1569 1575 RefPtr<WebColorPicker> m_colorPicker; -
trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h
r167280 r167698 81 81 82 82 BOOL _canSendTouchEventsAsynchronously; 83 unsigned _nativeWebTouchEventUniqueIdBeingSentSynchronously;84 83 85 84 RetainPtr<UITapGestureRecognizer> _singleTapGestureRecognizer; -
trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
r167624 r167698 292 292 { 293 293 NativeWebTouchEvent nativeWebTouchEvent(gestureRecognizer); 294 295 294 if (nativeWebTouchEvent.type() == WebKit::WebEvent::TouchStart) 296 295 _canSendTouchEventsAsynchronously = NO; 297 296 298 if (!_canSendTouchEventsAsynchronously) 299 _nativeWebTouchEventUniqueIdBeingSentSynchronously = nativeWebTouchEvent.uniqueId(); 300 301 _page->setShouldSendEventsSynchronously(!_canSendTouchEventsAsynchronously); 302 _page->handleTouchEvent(nativeWebTouchEvent); 303 _page->setShouldSendEventsSynchronously(false); 297 if (_canSendTouchEventsAsynchronously) 298 _page->handleTouchEventAsynchronously(nativeWebTouchEvent); 299 else 300 _page->handleTouchEventSynchronously(nativeWebTouchEvent); 304 301 } 305 302 … … 344 341 { 345 342 if (preventsNativeGesture) { 346 // If we are dispatching events synchronously and the event coming back is not the one we are sending, it is a callback347 // from an event sent asynchronously prior to the synchronous event. In that case, it should not use that information348 // to update UIWebTouchEventsGestureRecognizer.349 if (!_canSendTouchEventsAsynchronously && _nativeWebTouchEventUniqueIdBeingSentSynchronously != touchEvent.uniqueId())350 return;351 352 343 _canSendTouchEventsAsynchronously = YES; 353 344 [_touchEventGestureRecognizer setDefaultPrevented:YES]; -
trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp
r165746 r167698 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 55 55 : m_queue(WorkQueue::create("com.apple.WebKit.EventDispatcher")) 56 56 , m_recentWheelEventDeltaTracker(adoptPtr(new WheelEventDeltaTracker)) 57 #if ENABLE(IOS_TOUCH_EVENTS) 58 , m_touchEventsLock(SPINLOCK_INITIALIZER) 59 #endif 57 60 { 58 61 } … … 144 147 } 145 148 149 #if ENABLE(IOS_TOUCH_EVENTS) 150 void EventDispatcher::clearQueuedTouchEventsForPage(const WebPage& webPage) 151 { 152 SpinLockHolder locker(&m_touchEventsLock); 153 m_touchEvents.remove(webPage.pageID()); 154 } 155 156 void EventDispatcher::getQueuedTouchEventsForPage(const WebPage& webPage, TouchEventQueue& destinationQueue) 157 { 158 SpinLockHolder locker(&m_touchEventsLock); 159 destinationQueue = std::move(m_touchEvents.take(webPage.pageID())); 160 } 161 162 void EventDispatcher::touchEvent(uint64_t pageID, const WebKit::WebTouchEvent& touchEvent) 163 { 164 bool updateListWasEmpty; 165 { 166 SpinLockHolder locker(&m_touchEventsLock); 167 updateListWasEmpty = m_touchEvents.isEmpty(); 168 auto addResult = m_touchEvents.add(pageID, std::move(TouchEventQueue())); 169 if (addResult.isNewEntry) 170 addResult.iterator->value.append(touchEvent); 171 else { 172 TouchEventQueue& queuedEvents = addResult.iterator->value; 173 ASSERT(!queuedEvents.isEmpty()); 174 const WebTouchEvent& lastTouchEvent = queuedEvents.last(); 175 176 // Coalesce touch move events. 177 WebEvent::Type type = lastTouchEvent.type(); 178 if (type == WebEvent::TouchMove) 179 queuedEvents.last() = touchEvent; 180 else 181 queuedEvents.append(touchEvent); 182 } 183 } 184 185 if (updateListWasEmpty) 186 RunLoop::main().dispatch(bind(&EventDispatcher::dispatchTouchEvents, this)); 187 } 188 189 void EventDispatcher::dispatchTouchEvents() 190 { 191 HashMap<uint64_t, TouchEventQueue> localCopy; 192 { 193 SpinLockHolder locker(&m_touchEventsLock); 194 localCopy.swap(m_touchEvents); 195 } 196 197 for (auto& slot : localCopy) { 198 if (WebPage* webPage = WebProcess::shared().webPage(slot.key)) 199 webPage->dispatchAsynchronousTouchEvents(slot.value); 200 } 201 } 202 #endif 203 146 204 void EventDispatcher::dispatchWheelEvent(uint64_t pageID, const WebWheelEvent& wheelEvent) 147 205 { -
trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h
r163180 r167698 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include <WebCore/WheelEventDeltaTracker.h> 32 #include <WebEvent.h> 32 33 #include <wtf/HashMap.h> 33 34 #include <wtf/Noncopyable.h> 34 35 #include <wtf/RefPtr.h> 36 #include <wtf/TCSpinLock.h> 35 37 #include <wtf/ThreadingPrimitives.h> 36 38 … … 55 57 #endif 56 58 59 #if ENABLE(IOS_TOUCH_EVENTS) 60 typedef Vector<WebTouchEvent, 1> TouchEventQueue; 61 62 void clearQueuedTouchEventsForPage(const WebPage&); 63 void getQueuedTouchEventsForPage(const WebPage&, TouchEventQueue&); 64 #endif 65 57 66 void initializeConnection(IPC::Connection*); 58 67 … … 65 74 // Message handlers 66 75 void wheelEvent(uint64_t pageID, const WebWheelEvent&, bool canRubberBandAtLeft, bool canRubberBandAtRight, bool canRubberBandAtTop, bool canRubberBandAtBottom); 76 #if ENABLE(IOS_TOUCH_EVENTS) 77 void touchEvent(uint64_t pageID, const WebTouchEvent&); 78 #endif 79 67 80 68 81 // This is called on the main thread. 69 82 void dispatchWheelEvent(uint64_t pageID, const WebWheelEvent&); 83 #if ENABLE(IOS_TOUCH_EVENTS) 84 void dispatchTouchEvents(); 85 #endif 70 86 71 87 #if ENABLE(ASYNC_SCROLLING) … … 80 96 #endif 81 97 OwnPtr<WebCore::WheelEventDeltaTracker> m_recentWheelEventDeltaTracker; 98 #if ENABLE(IOS_TOUCH_EVENTS) 99 SpinLock m_touchEventsLock; 100 HashMap<uint64_t, TouchEventQueue> m_touchEvents; 101 #endif 82 102 }; 83 103 -
trunk/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in
r160742 r167698 23 23 messages -> EventDispatcher { 24 24 WheelEvent(uint64_t pageID, WebKit::WebWheelEvent event, bool canRubberBandAtLeft, bool canRubberBandAtRight, bool canRubberBandAtTop, bool canRubberBandAtBottom) 25 #if ENABLE(IOS_TOUCH_EVENTS) 26 TouchEvent(uint64_t pageID, WebKit::WebTouchEvent event) 27 #endif 25 28 } -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
r167686 r167698 1949 1949 return page->mainFrame().eventHandler().handleTouchEvent(platform(touchEvent)); 1950 1950 } 1951 1951 #endif 1952 1953 #if ENABLE(IOS_TOUCH_EVENTS) 1954 void WebPage::dispatchTouchEvent(const WebTouchEvent& touchEvent, bool& handled) 1955 { 1956 m_lastInteractionLocation = touchEvent.position(); 1957 CurrentEvent currentEvent(touchEvent); 1958 handled = handleTouchEvent(touchEvent, m_page.get()); 1959 } 1960 1961 void WebPage::touchEventSync(const WebTouchEvent& touchEvent, bool& handled) 1962 { 1963 EventDispatcher::TouchEventQueue queuedEvents; 1964 WebProcess::shared().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents); 1965 dispatchAsynchronousTouchEvents(queuedEvents); 1966 1967 dispatchTouchEvent(touchEvent, handled); 1968 } 1969 #elif ENABLE(TOUCH_EVENTS) 1952 1970 void WebPage::touchEvent(const WebTouchEvent& touchEvent) 1953 1971 { 1954 #if PLATFORM(IOS) 1955 m_lastInteractionLocation = touchEvent.position(); 1956 #endif 1972 1957 1973 bool handled = false; 1958 1974 if (canHandleUserEvents()) { … … 1966 1982 void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled) 1967 1983 { 1968 #if PLATFORM(IOS)1969 m_lastInteractionLocation = touchEvent.position();1970 #endif1971 1984 CurrentEvent currentEvent(touchEvent); 1972 1985 handled = handleTouchEvent(touchEvent, m_page.get()); … … 4240 4253 m_userHasChangedPageScaleFactor = false; 4241 4254 4255 WebProcess::shared().eventDispatcher().clearQueuedTouchEventsForPage(*this); 4256 4242 4257 Document* document = frame->coreFrame()->document(); 4243 4258 if (document->isImageDocument()) -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h
r167686 r167698 479 479 WebCore::IntRect rectForElementAtInteractionLocation(); 480 480 481 void dispatchAsynchronousTouchEvents(const Vector<WebTouchEvent, 1>& queue); 481 482 #if ENABLE(INSPECTOR) 482 483 void showInspectorIndication(); … … 706 707 void applicationDidBecomeActive(); 707 708 void zoomToRect(WebCore::FloatRect, double minimumScale, double maximumScale); 709 void dispatchTouchEvent(const WebTouchEvent&, bool& handled); 708 710 #endif 709 711 … … 856 858 void keyEvent(const WebKeyboardEvent&); 857 859 void keyEventSyncForTesting(const WebKeyboardEvent&, bool&); 858 #if ENABLE(TOUCH_EVENTS) 860 #if ENABLE(IOS_TOUCH_EVENTS) 861 void touchEventSync(const WebTouchEvent&, bool& handled); 862 #elif ENABLE(TOUCH_EVENTS) 859 863 void touchEvent(const WebTouchEvent&); 860 864 void touchEventSyncForTesting(const WebTouchEvent&, bool& handled); -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
r167686 r167698 82 82 #endif 83 83 84 #if ENABLE(TOUCH_EVENTS) 84 #if ENABLE(IOS_TOUCH_EVENTS) 85 TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) 86 #endif 87 #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS) 85 88 TouchEvent(WebKit::WebTouchEvent event) 86 89 TouchEventSyncForTesting(WebKit::WebTouchEvent event) -> (bool handled) -
trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm
r167624 r167698 2060 2060 } 2061 2061 2062 void WebPage::dispatchAsynchronousTouchEvents(const Vector<WebTouchEvent, 1>& queue) 2063 { 2064 bool ignored; 2065 for (const WebTouchEvent& event : queue) 2066 dispatchTouchEvent(event, ignored); 2067 } 2068 2062 2069 } // namespace WebKit 2063 2070
Note: See TracChangeset
for help on using the changeset viewer.