WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
patch (text/plain), 39.54 KB, created by
Levi Weintraub
on 2012-12-16 19:08:10 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Levi Weintraub
Created:
2012-12-16 19:08:10 PST
Size:
39.54 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 137865) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,79 @@ >+2012-12-16 Levi Weintraub <leviw@chromium.org> >+ >+ Add support for tracking hit test rectangles to enable fast event rejection in the compositor >+ https://bugs.webkit.org/show_bug.cgi?id=103914 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adding support for tracking hit test target regions for the purpose of performing initial hit testing >+ in the compositor to avoid blocking scrolling on the main thread while waiting to hit test events that >+ aren't occuring in regions with handlers. This is initially being done to avoid having to go to the main >+ thread when scrolling by flicking on touch devices when the flick occurs outside a tracked touch event >+ region. This patch includes the implementation to turn this on in Chromium. >+ >+ To accomplish this goal, Document will now keep a counted hash set of nodes with touch event handlers >+ instead of only an unsigned integer of the total count. ScrollingCoordinator then updates the compositor >+ when new touch event handlers are registered or removed, or after layout much like how >+ nonFastScrollableRegions are currently tracked. >+ >+ This implementation will not properly update the hit test rects when the renderers are inside a sub- >+ tree that scrolls. >+ >+ This change was initially rolled out due to stale Node pointers in Document's touchEventTargets. This >+ patch adds a callback to remove the Node from that structure to Node's destructor. This is covered >+ by the touch-target-removed-crash.html test case which is also added. >+ >+ Test: platform/chromium/fast/events/touch/compositor-touch-hit-rects.html >+ platform/chromium/fast/events/touch/touch-target-removed-crash.html >+ >+ * dom/Document.cpp: >+ (WebCore::Document::Document): Added a HashCountedSet of touch target nodes. Note: DOMWindow targets >+ are stored as the Document they point to. >+ (WebCore::Document::didAddTouchEventHandler): Changed to keep track of the handler instead of a count, and >+ to update the ScrollingCoordinator with the change. >+ (WebCore::Document::didRemoveTouchEventHandler): Ditto. >+ * dom/Document.h: >+ (WebCore::Document::hasTouchEventHandlers): It's no longer O(1) to get the count of touch handlers, so >+ expose whether there are any or not. >+ (WebCore::Document::touchEventTargets): >+ * dom/Node.cpp: >+ (WebCore::Node::didMoveToNewDocument): >+ (WebCore::tryAddEventListener): >+ (WebCore::tryRemoveEventListener): >+ * history/CachedFrame.cpp: >+ (WebCore::CachedFrameBase::restore): >+ * html/HTMLInputElement.cpp: >+ (WebCore::HTMLInputElement::~HTMLInputElement): >+ (WebCore::HTMLInputElement::updateType): >+ * page/DOMWindow.cpp: >+ (WebCore::DOMWindow::addEventListener): Add the Document to the touch target set instead of DOMWindow. >+ (WebCore::DOMWindow::removeEventListener): >+ * page/EventHandler.cpp: >+ (WebCore::EventHandler::handleTouchEvent): >+ * page/Frame.cpp: >+ (WebCore::Frame::setDocument): >+ * page/scrolling/ScrollingCoordinator.cpp: >+ (WebCore::ScrollingCoordinator::computeAbsoluteTouchEventTargetRects): Walk the renderers for event handler >+ nodes and generate the absolute hit testing rects. >+ * page/scrolling/ScrollingCoordinator.h: >+ (WebCore::ScrollingCoordinator::setTouchEventTargetRectsChanged): Hook to pass along the hit test rects to >+ the scrolling tree/compositor. >+ (ScrollingCoordinator): >+ * page/scrolling/chromium/ScrollingCoordinatorChromium.cpp: >+ (WebCore::ScrollingCoordinatorChromium::frameViewLayoutUpdated): >+ (WebCore::ScrollingCoordinatorChromium::setTouchEventTargetRectsChanged): >+ (WebCore::ScrollingCoordinatorChromium::setNonFastScrollableRegion): >+ (WebCore::ScrollingCoordinatorChromium::setTouchEventTargetRects): >+ * page/scrolling/chromium/ScrollingCoordinatorChromium.h: >+ (ScrollingCoordinatorChromium): >+ * testing/Internals.cpp: >+ (WebCore::Internals::touchEventHandlerCount): Changed to do the work to calculate the actual count since >+ it's no longer stored as an int in Document. >+ (WebCore::Internals::touchEventTargetClientRects): >+ * testing/Internals.h: >+ (Internals): >+ * testing/Internals.idl: >+ > 2012-12-16 Levi Weintraub <leviw@chromium.org> > > Push pixel snapping logic into TransformState >Index: Source/WebCore/dom/Document.cpp >=================================================================== >--- Source/WebCore/dom/Document.cpp (revision 137865) >+++ Source/WebCore/dom/Document.cpp (working copy) >@@ -498,9 +498,6 @@ Document::Document(Frame* frame, const K > , m_writeRecursionIsTooDeep(false) > , m_writeRecursionDepth(0) > , m_wheelEventHandlerCount(0) >-#if ENABLE(TOUCH_EVENTS) >- , m_touchEventHandlerCount(0) >-#endif > , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired) > , m_scheduledTasksAreSuspended(false) > , m_visualUpdatesAllowed(true) >@@ -613,6 +610,10 @@ Document::~Document() > ASSERT(!m_parentTreeScope); > ASSERT(!m_guardRefCount); > >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ if (Document* ownerDocument = this->ownerDocument()) >+ ownerDocument->didRemoveEventTargetNode(this); >+#endif > // FIXME: Should we reset m_domWindow when we detach from the Frame? > if (m_domWindow) > m_domWindow->resetUnlessSuspendedForPageCache(); >@@ -5599,36 +5600,68 @@ void Document::didRemoveWheelEventHandle > wheelEventHandlerCountChanged(this); > } > >-void Document::didAddTouchEventHandler() >+void Document::didAddTouchEventHandler(Node* handler) > { > #if ENABLE(TOUCH_EVENTS) >- ++m_touchEventHandlerCount; >- if (m_touchEventHandlerCount > 1) >+ if (!m_touchEventTargets.get()) >+ m_touchEventTargets = adoptPtr(new TouchEventTargetSet); >+ m_touchEventTargets->add(handler); >+ if (Document* parent = parentDocument()) { >+ parent->didAddTouchEventHandler(this); > return; >- if (Page* page = this->page()) >- page->chrome()->client()->needTouchEvents(true); >+ } >+ if (Page* page = this->page()) { >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) >+ scrollingCoordinator->touchEventTargetRectsDidChange(this); >+#endif >+ if (m_touchEventTargets->size() == 1) >+ page->chrome()->client()->needTouchEvents(true); >+ } >+#else >+ UNUSED_PARAM(handler); > #endif > } > >-void Document::didRemoveTouchEventHandler() >+void Document::didRemoveTouchEventHandler(Node* handler) > { > #if ENABLE(TOUCH_EVENTS) >- ASSERT(m_touchEventHandlerCount); >- --m_touchEventHandlerCount; >- if (m_touchEventHandlerCount) >+ if (!m_touchEventTargets.get()) >+ return; >+ ASSERT(m_touchEventTargets->contains(handler)); >+ m_touchEventTargets->remove(handler); >+ if (Document* parent = parentDocument()) { >+ parent->didRemoveTouchEventHandler(this); > return; >+ } > > Page* page = this->page(); > if (!page) > return; >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) >+ scrollingCoordinator->touchEventTargetRectsDidChange(this); >+#endif >+ if (m_touchEventTargets->size()) >+ return; > for (const Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { >- if (frame->document() && frame->document()->touchEventHandlerCount()) >+ if (frame->document() && frame->document()->hasTouchEventHandlers()) > return; > } > page->chrome()->client()->needTouchEvents(false); >+#else >+ UNUSED_PARAM(handler); > #endif > } > >+#if ENABLE(TOUCH_EVENT_TRACKING) >+void Document::didRemoveEventTargetNode(Node* handler) >+{ >+ if (m_touchEventTargets.get()) >+ m_touchEventTargets->removeAll(handler); >+} >+#endif >+ > HTMLIFrameElement* Document::seamlessParentIFrame() const > { > if (!shouldDisplaySeamlesslyWithParent()) >Index: Source/WebCore/dom/Document.h >=================================================================== >--- Source/WebCore/dom/Document.h (revision 137865) >+++ Source/WebCore/dom/Document.h (working copy) >@@ -207,6 +207,8 @@ enum NodeListInvalidationType { > }; > const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1; > >+typedef HashCountedSet<Node*> TouchEventTargetSet; >+ > class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext { > public: > static PassRefPtr<Document> create(Frame* frame, const KURL& url) >@@ -1118,13 +1120,23 @@ public: > void didRemoveWheelEventHandler(); > > #if ENABLE(TOUCH_EVENTS) >- unsigned touchEventHandlerCount() const { return m_touchEventHandlerCount; } >+ bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; } > #else >- unsigned touchEventHandlerCount() const { return 0; } >+ bool hasTouchEventHandlers() const { return false; } >+#endif >+ >+ void didAddTouchEventHandler(Node*); >+ void didRemoveTouchEventHandler(Node*); >+ >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ void didRemoveEventTargetNode(Node*); > #endif > >- void didAddTouchEventHandler(); >- void didRemoveTouchEventHandler(); >+#if ENABLE(TOUCH_EVENTS) >+ const TouchEventTargetSet* touchEventTargets() const { return m_touchEventTargets.get(); } >+#else >+ const TouchEventTargetSet* touchEventTargets() const { return 0; } >+#endif > > bool visualUpdatesAllowed() const { return m_visualUpdatesAllowed; } > >@@ -1503,7 +1515,7 @@ private: > > unsigned m_wheelEventHandlerCount; > #if ENABLE(TOUCH_EVENTS) >- unsigned m_touchEventHandlerCount; >+ OwnPtr<TouchEventTargetSet> m_touchEventTargets; > #endif > > #if ENABLE(REQUEST_ANIMATION_FRAME) >Index: Source/WebCore/dom/Node.cpp >=================================================================== >--- Source/WebCore/dom/Node.cpp (revision 137865) >+++ Source/WebCore/dom/Node.cpp (working copy) >@@ -412,8 +412,13 @@ Node::~Node() > if (hasRareData()) > clearRareData(); > >- if (hasEventTargetData()) >+ if (hasEventTargetData()) { >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ if (m_document) >+ m_document->didRemoveEventTargetNode(this); >+#endif > clearEventTargetData(); >+ } > > if (renderer()) > detach(); >@@ -2125,8 +2130,8 @@ void Node::didMoveToNewDocument(Document > for (size_t i = 0; i < touchEventNames.size(); ++i) { > const EventListenerVector& listeners = getEventListeners(touchEventNames[i]); > for (size_t j = 0; j < listeners.size(); ++j) { >- oldDocument->didRemoveTouchEventHandler(); >- document()->didAddTouchEventHandler(); >+ oldDocument->didRemoveTouchEventHandler(this); >+ document()->didAddTouchEventHandler(this); > } > } > >@@ -2155,7 +2160,7 @@ static inline bool tryAddEventListener(N > if (eventType == eventNames().mousewheelEvent) > document->didAddWheelEventHandler(); > else if (eventNames().isTouchEventType(eventType)) >- document->didAddTouchEventHandler(); >+ document->didAddTouchEventHandler(targetNode); > } > > return true; >@@ -2177,7 +2182,7 @@ static inline bool tryRemoveEventListene > if (eventType == eventNames().mousewheelEvent) > document->didRemoveWheelEventHandler(); > else if (eventNames().isTouchEventType(eventType)) >- document->didRemoveTouchEventHandler(); >+ document->didRemoveTouchEventHandler(targetNode); > } > > return true; >Index: Source/WebCore/history/CachedFrame.cpp >=================================================================== >--- Source/WebCore/history/CachedFrame.cpp (revision 137865) >+++ Source/WebCore/history/CachedFrame.cpp (working copy) >@@ -134,7 +134,7 @@ void CachedFrameBase::restore() > m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue()); > > #if ENABLE(TOUCH_EVENTS) >- if (m_document->touchEventHandlerCount()) >+ if (m_document->hasTouchEventHandlers()) > m_document->page()->chrome()->client()->needTouchEvents(true); > #endif > >Index: Source/WebCore/html/HTMLInputElement.cpp >=================================================================== >--- Source/WebCore/html/HTMLInputElement.cpp (revision 137865) >+++ Source/WebCore/html/HTMLInputElement.cpp (working copy) >@@ -163,7 +163,7 @@ HTMLInputElement::~HTMLInputElement() > document()->formController()->checkedRadioButtons().removeButton(this); > #if ENABLE(TOUCH_EVENTS) > if (m_hasTouchEventHandler) >- document()->didRemoveTouchEventHandler(); >+ document()->didRemoveTouchEventHandler(this); > #endif > } > >@@ -489,9 +489,9 @@ void HTMLInputElement::updateType() > bool hasTouchEventHandler = m_inputType->hasTouchEventHandler(); > if (hasTouchEventHandler != m_hasTouchEventHandler) { > if (hasTouchEventHandler) >- document()->didAddTouchEventHandler(); >+ document()->didAddTouchEventHandler(this); > else >- document()->didRemoveTouchEventHandler(); >+ document()->didRemoveTouchEventHandler(this); > m_hasTouchEventHandler = hasTouchEventHandler; > } > #endif >Index: Source/WebCore/page/DOMWindow.cpp >=================================================================== >--- Source/WebCore/page/DOMWindow.cpp (revision 137865) >+++ Source/WebCore/page/DOMWindow.cpp (working copy) >@@ -1582,7 +1582,7 @@ bool DOMWindow::addEventListener(const A > if (eventType == eventNames().mousewheelEvent) > document->didAddWheelEventHandler(); > else if (eventNames().isTouchEventType(eventType)) >- document->didAddTouchEventHandler(); >+ document->didAddTouchEventHandler(document); > else if (eventType == eventNames().storageEvent) > didAddStorageEventListener(this); > } >@@ -1613,7 +1613,7 @@ bool DOMWindow::removeEventListener(cons > if (eventType == eventNames().mousewheelEvent) > document->didRemoveWheelEventHandler(); > else if (eventNames().isTouchEventType(eventType)) >- document->didRemoveTouchEventHandler(); >+ document->didRemoveTouchEventHandler(document); > } > > if (eventType == eventNames().unloadEvent) >Index: Source/WebCore/page/EventHandler.cpp >=================================================================== >--- Source/WebCore/page/EventHandler.cpp (revision 137865) >+++ Source/WebCore/page/EventHandler.cpp (working copy) >@@ -3769,7 +3769,7 @@ bool EventHandler::handleTouchEvent(cons > } > if (!doc) > continue; >- if (!doc->touchEventHandlerCount()) >+ if (!doc->hasTouchEventHandlers()) > continue; > m_originatingTouchPointTargets.set(touchPointTargetKey, node); > touchTarget = node; >@@ -3794,7 +3794,7 @@ bool EventHandler::handleTouchEvent(cons > Document* doc = touchTarget->toNode()->document(); > if (!doc) > continue; >- if (!doc->touchEventHandlerCount()) >+ if (!doc->hasTouchEventHandlers()) > continue; > Frame* targetFrame = doc->frame(); > if (!targetFrame) >Index: Source/WebCore/page/Frame.cpp >=================================================================== >--- Source/WebCore/page/Frame.cpp (revision 137865) >+++ Source/WebCore/page/Frame.cpp (working copy) >@@ -309,7 +309,7 @@ void Frame::setDocument(PassRefPtr<Docum > if (m_page && m_page->mainFrame() == this) { > notifyChromeClientWheelEventHandlerCountChanged(); > #if ENABLE(TOUCH_EVENTS) >- if (m_doc && m_doc->touchEventHandlerCount()) >+ if (m_doc && m_doc->hasTouchEventHandlers()) > m_page->chrome()->client()->needTouchEvents(true); > #endif > } >Index: Source/WebCore/page/scrolling/ScrollingCoordinator.cpp >=================================================================== >--- Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (revision 137865) >+++ Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (working copy) >@@ -27,6 +27,7 @@ > > #include "ScrollingCoordinator.h" > >+#include "Document.h" > #include "Frame.h" > #include "FrameView.h" > #include "GraphicsLayer.h" >@@ -177,6 +178,57 @@ Region ScrollingCoordinator::computeNonF > return nonFastScrollableRegion; > } > >+#if ENABLE(TOUCH_EVENT_TRACKING) >+static void accumulateRendererTouchEventTargetRects(Vector<IntRect>& rects, const RenderObject* renderer) >+{ >+ // FIXME: This method is O(N^2) as it walks the tree to the root for every renderer. RenderGeometryMap would fix this. >+ rects.append(enclosingIntRect(renderer->clippedOverflowRectForRepaint(0))); >+ if (renderer->isRenderBlock()) { >+ const RenderBlock* block = toRenderBlock(renderer); >+ for (RenderObject* child = block->firstChild(); child; child = child->nextSibling()) >+ accumulateRendererTouchEventTargetRects(rects, child); >+ } >+} >+ >+static void accumulateDocumentEventTargetRects(Vector<IntRect>& rects, const Document* document) >+{ >+ ASSERT(document); >+ if (!document->touchEventTargets()) >+ return; >+ >+ const TouchEventTargetSet* targets = document->touchEventTargets(); >+ for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { >+ const Node* touchTarget = iter->key; >+ if (!touchTarget->inDocument()) >+ continue; >+ >+ if (touchTarget == document) { >+ if (RenderView* view = document->renderView()) >+ rects.append(enclosingIntRect(view->clippedOverflowRectForRepaint(0))); >+ return; >+ } >+ >+ if (touchTarget->isDocumentNode() && touchTarget != document) { >+ accumulateDocumentEventTargetRects(rects, static_cast<const Document*>(touchTarget)); >+ continue; >+ } >+ >+ if (RenderObject* renderer = touchTarget->renderer()) >+ accumulateRendererTouchEventTargetRects(rects, renderer); >+ } >+} >+ >+void ScrollingCoordinator::computeAbsoluteTouchEventTargetRects(const Document* document, Vector<IntRect>& rects) >+{ >+ ASSERT(document); >+ if (!document->view()) >+ return; >+ >+ // FIXME: These rects won't be properly updated if the renderers are in a sub-tree that scrolls. >+ accumulateDocumentEventTargetRects(rects, document); >+} >+#endif >+ > unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount() > { > unsigned wheelEventHandlerCount = 0; >Index: Source/WebCore/page/scrolling/ScrollingCoordinator.h >=================================================================== >--- Source/WebCore/page/scrolling/ScrollingCoordinator.h (revision 137865) >+++ Source/WebCore/page/scrolling/ScrollingCoordinator.h (working copy) >@@ -29,6 +29,7 @@ > #include "IntRect.h" > #include "LayoutRect.h" > #include "PlatformWheelEvent.h" >+#include "RenderObject.h" > #include "ScrollTypes.h" > #include "Timer.h" > #include <wtf/Forward.h> >@@ -50,6 +51,7 @@ typedef uint64_t ScrollingNodeID; > > enum ScrollingNodeType { ScrollingNode, FixedNode }; > >+class Document; > class Frame; > class FrameView; > class GraphicsLayer; >@@ -149,6 +151,11 @@ public: > virtual void scrollableAreaScrollLayerDidChange(ScrollableArea*, GraphicsLayer*) { } > virtual void setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool) { } > virtual void setLayerIsFixedToContainerLayer(GraphicsLayer*, bool) { } >+ virtual void touchEventTargetRectsDidChange(const Document*) { } >+ >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ void computeAbsoluteTouchEventTargetRects(const Document*, Vector<IntRect>&); >+#endif > > static String mainThreadScrollingReasonsAsText(MainThreadScrollingReasons); > String mainThreadScrollingReasonsAsText() const; >Index: Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp >=================================================================== >--- Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp (revision 137865) >+++ Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp (working copy) >@@ -115,6 +115,30 @@ void ScrollingCoordinatorChromium::frame > // frame view whose layout was updated is not the main frame. > Region nonFastScrollableRegion = computeNonFastScrollableRegion(m_page->mainFrame(), IntPoint()); > setNonFastScrollableRegion(nonFastScrollableRegion); >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ Vector<IntRect> touchEventTargetRects; >+ computeAbsoluteTouchEventTargetRects(m_page->mainFrame()->document(), touchEventTargetRects); >+ setTouchEventTargetRects(touchEventTargetRects); >+#endif >+} >+ >+void ScrollingCoordinatorChromium::touchEventTargetRectsDidChange(const Document* document) >+{ >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ // Wait until after layout to update. >+ if (m_page->mainFrame()->view()->needsLayout()) >+ return; >+ >+ // We won't necessarily get a setScrollLayer() call before this one, so grab the root ourselves. >+ setScrollLayer(scrollLayerForFrameView(m_page->mainFrame()->view())); >+ if (m_private->scrollLayer()) { >+ Vector<IntRect> touchEventTargetRects; >+ computeAbsoluteTouchEventTargetRects(document, touchEventTargetRects); >+ setTouchEventTargetRects(touchEventTargetRects); >+ } >+#else >+ UNUSED_PARAM(document); >+#endif > } > > void ScrollingCoordinatorChromium::frameViewRootLayerDidChange(FrameView* frameView) >@@ -209,6 +233,18 @@ void ScrollingCoordinatorChromium::setNo > } > } > >+void ScrollingCoordinatorChromium::setTouchEventTargetRects(const Vector<IntRect>& absoluteHitTestRects) >+{ >+ // We won't necessarily get a setScrollLayer() call before this one, so grab the root ourselves. >+ setScrollLayer(scrollLayerForFrameView(m_page->mainFrame()->view())); >+ if (m_private->scrollLayer()) { >+ WebVector<WebRect> webRects(absoluteHitTestRects.size()); >+ for (size_t i = 0; i < absoluteHitTestRects.size(); ++i) >+ webRects[i] = absoluteHitTestRects[i]; >+ m_private->scrollLayer()->setTouchEventHandlerRegion(webRects); >+ } >+} >+ > void ScrollingCoordinatorChromium::setWheelEventHandlerCount(unsigned wheelEventHandlerCount) > { > // We won't necessarily get a setScrollLayer() call before this one, so grab the root ourselves. >Index: Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.h >=================================================================== >--- Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.h (revision 137865) >+++ Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.h (working copy) >@@ -68,12 +68,16 @@ public: > // Should be called whenever the scrollable layer for the given scroll area changes. > virtual void scrollableAreaScrollLayerDidChange(ScrollableArea*, GraphicsLayer*); > >+ // Should be called whenever touch handlers are registered, removed, or moved. >+ virtual void touchEventTargetRectsDidChange(const Document*) OVERRIDE; >+ > private: > virtual void recomputeWheelEventHandlerCountForFrameView(FrameView*); > virtual void setShouldUpdateScrollLayerPositionOnMainThread(MainThreadScrollingReasons); > > void setScrollLayer(GraphicsLayer*); > void setNonFastScrollableRegion(const Region&); >+ void setTouchEventTargetRects(const Vector<IntRect>&); > void setWheelEventHandlerCount(unsigned); > PassOwnPtr<WebKit::WebScrollbarLayer> createScrollbarLayer(Scrollbar*, WebKit::WebLayer* scrollLayer, GraphicsLayer* scrollbarGraphicsLayer, FrameView*); > >Index: Source/WebCore/testing/Internals.cpp >=================================================================== >--- Source/WebCore/testing/Internals.cpp (revision 137865) >+++ Source/WebCore/testing/Internals.cpp (working copy) >@@ -73,6 +73,7 @@ > #include "RenderTreeAsText.h" > #include "RuntimeEnabledFeatures.h" > #include "SchemeRegistry.h" >+#include "ScrollingCoordinator.h" > #include "SelectRuleFeatureSet.h" > #include "SerializedScriptValue.h" > #include "Settings.h" >@@ -1200,8 +1201,38 @@ unsigned Internals::touchEventHandlerCou > return 0; > } > >- return document->touchEventHandlerCount(); >+ const TouchEventTargetSet* touchHandlers = document->touchEventTargets(); >+ if (!touchHandlers) >+ return 0; >+ >+ unsigned count = 0; >+ for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter) >+ count += iter->value; >+ return count; >+} >+ >+#if ENABLE(TOUCH_EVENT_TRACKING) >+PassRefPtr<ClientRectList> Internals::touchEventTargetClientRects(Document* document, ExceptionCode& ec) >+{ >+ if (!document || !document->view() || !document->page()) { >+ ec = INVALID_ACCESS_ERR; >+ return 0; >+ } >+ if (!document->page()->scrollingCoordinator()) >+ return ClientRectList::create(); >+ >+ document->updateLayoutIgnorePendingStylesheets(); >+ >+ Vector<IntRect> absoluteRects; >+ document->page()->scrollingCoordinator()->computeAbsoluteTouchEventTargetRects(document, absoluteRects); >+ Vector<FloatQuad> absoluteQuads(absoluteRects.size()); >+ >+ for (size_t i = 0; i < absoluteRects.size(); ++i) >+ absoluteQuads[i] = FloatQuad(absoluteRects[i]); >+ >+ return ClientRectList::create(absoluteQuads); > } >+#endif > > PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int x, int y, unsigned topPadding, unsigned rightPadding, > unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, ExceptionCode& ec) const >Index: Source/WebCore/testing/Internals.h >=================================================================== >--- Source/WebCore/testing/Internals.h (revision 137865) >+++ Source/WebCore/testing/Internals.h (working copy) >@@ -171,6 +171,9 @@ public: > > unsigned wheelEventHandlerCount(Document*, ExceptionCode&); > unsigned touchEventHandlerCount(Document*, ExceptionCode&); >+#if ENABLE(TOUCH_EVENT_TRACKING) >+ PassRefPtr<ClientRectList> touchEventTargetClientRects(Document*, ExceptionCode&); >+#endif > > PassRefPtr<NodeList> nodesFromRect(Document*, int x, int y, unsigned topPadding, unsigned rightPadding, > unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, ExceptionCode&) const; >Index: Source/WebCore/testing/Internals.idl >=================================================================== >--- Source/WebCore/testing/Internals.idl (revision 137865) >+++ Source/WebCore/testing/Internals.idl (working copy) >@@ -139,6 +139,9 @@ > > unsigned long wheelEventHandlerCount(in Document document) raises (DOMException); > unsigned long touchEventHandlerCount(in Document document) raises (DOMException); >+#if defined(ENABLE_TOUCH_EVENT_TRACKING) && ENABLE_TOUCH_EVENT_TRACKING >+ ClientRectList touchEventTargetClientRects(in Document document) raises (DOMException); >+#endif > > NodeList nodesFromRect(in Document document, in long x, in long y, > in unsigned long topPadding, in unsigned long rightPadding, in unsigned long bottomPadding, in unsigned long leftPadding, >Index: Source/WebKit/chromium/ChangeLog >=================================================================== >--- Source/WebKit/chromium/ChangeLog (revision 137865) >+++ Source/WebKit/chromium/ChangeLog (working copy) >@@ -1,3 +1,17 @@ >+2012-12-16 Levi Weintraub <leviw@chromium.org> >+ >+ Add support for tracking hit test rectangles to enable fast event rejection in the compositor >+ https://bugs.webkit.org/show_bug.cgi?id=103914 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Enabling touch event target region tracking. >+ >+ * features.gypi: >+ * src/WebPluginContainerImpl.cpp: >+ (WebKit::WebPluginContainerImpl::requestTouchEventType): >+ (WebKit::WebPluginContainerImpl::~WebPluginContainerImpl): >+ > 2012-12-16 Levi Weintraub <leviw@chromium.org> > > Push pixel snapping logic into TransformState >Index: Source/WebKit/chromium/features.gypi >=================================================================== >--- Source/WebKit/chromium/features.gypi (revision 137865) >+++ Source/WebKit/chromium/features.gypi (working copy) >@@ -116,6 +116,7 @@ > 'ENABLE_TOUCH_ADJUSTMENT=1', > 'ENABLE_TOUCH_EVENTS=<(enable_touch_events)', > 'ENABLE_TOUCH_ICON_LOADING=<(enable_touch_icon_loading)', >+ 'ENABLE_TOUCH_EVENT_TRACKING=<(enable_touch_events)', > 'ENABLE_TOUCH_SLIDER=1', > 'ENABLE_USER_TIMING=1', > 'ENABLE_V8_SCRIPT_DEBUG_SERVER=1', >Index: Source/WebKit/chromium/src/WebPluginContainerImpl.cpp >=================================================================== >--- Source/WebKit/chromium/src/WebPluginContainerImpl.cpp (revision 137865) >+++ Source/WebKit/chromium/src/WebPluginContainerImpl.cpp (working copy) >@@ -527,9 +527,9 @@ void WebPluginContainerImpl::requestTouc > return; > m_touchEventRequestType = requestType; > if (m_touchEventRequestType != TouchEventRequestTypeNone) >- m_element->document()->didAddTouchEventHandler(); >+ m_element->document()->didAddTouchEventHandler(m_element); > else >- m_element->document()->didRemoveTouchEventHandler(); >+ m_element->document()->didRemoveTouchEventHandler(m_element); > } > > void WebPluginContainerImpl::setWantsWheelEvents(bool wantsWheelEvents) >@@ -672,7 +672,7 @@ WebPluginContainerImpl::WebPluginContain > WebPluginContainerImpl::~WebPluginContainerImpl() > { > if (m_touchEventRequestType != TouchEventRequestTypeNone) >- m_element->document()->didRemoveTouchEventHandler(); >+ m_element->document()->didRemoveTouchEventHandler(m_element); > > for (size_t i = 0; i < m_pluginLoadObservers.size(); ++i) > m_pluginLoadObservers[i]->clearPluginContainer(); >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 137865) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,15 @@ >+2012-12-16 Levi Weintraub <leviw@chromium.org> >+ >+ Add support for tracking hit test rectangles to enable fast event rejection in the compositor >+ https://bugs.webkit.org/show_bug.cgi?id=103914 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * platform/chromium/fast/events/touch/compositor-touch-hit-rects-expected.txt: Added. >+ * platform/chromium/fast/events/touch/compositor-touch-hit-rects.html: Added. >+ * platform/chromium/fast/events/touch/touch-target-removed-crash-expected.txt: Added. >+ * platform/chromium/fast/events/touch/touch-target-removed-crash.html: Added. >+ > 2012-12-16 Kentaro Hara <haraken@chromium.org> > > Unreviewed. Rebaselined virtual/gpu/compositedscrolling/scrollbars/scrollbar-orientation.html. >Index: LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects-expected.txt >=================================================================== >--- LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects-expected.txt (revision 0) >+++ LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects-expected.txt (revision 0) >@@ -0,0 +1,46 @@ >+This tests verifies the hit test regions given to the compositor. It can only be run in DumpRenderTree. The outputted rects should cover the hit test regions of all the listed elements. >+ >+normalFlow[0]: (8, 72, 784, 10) >+normalFlow[1]: (8, 72, 784, 10) >+normalFlow[2]: (128, 72, 30, 10) >+normalFlow[3]: (8, 72, 784, 10) >+absoluteChildContainer[0]: (8, 162, 784, 10) >+absoluteChildContainer[1]: (8, 162, 784, 10) >+absoluteChildContainer[2]: (8, 162, 784, 10) >+absoluteChildContainer[3]: (118, 300, 140, 10) >+absoluteChildContainer[4]: (118, 300, 140, 10) >+relativeChildContainer[0]: (8, 272, 784, 10) >+relativeChildContainer[1]: (8, 272, 784, 10) >+relativeChildContainer[2]: (8, 272, 784, 10) >+relativeChildContainer[3]: (128, 472, 140, 10) >+overhangingContainer[0]: (8, 362, 784, 10) >+overhangingContainer[1]: (8, 362, 110, 80) >+overhangingContainer[2]: (8, 362, 110, 80) >+transformedChildContainer[0]: (62, 421, 661, 32) >+transformedChildContainer[1]: (62, 421, 661, 32) >+transformedChildContainer[2]: (8, 432, 769, 10) >+continuation[0]: (108, 502, 100, 10) >+ >+This tests verifies the hit test regions given to the compositor. It can only be run in DumpRenderTree. The outputted rects should cover the hit test regions of all the listed elements. >+ >+normalFlow[0]: (8, 72, 784, 10) >+normalFlow[1]: (8, 72, 784, 10) >+normalFlow[2]: (128, 72, 30, 10) >+normalFlow[3]: (8, 72, 784, 10) >+absoluteChildContainer[0]: (8, 162, 784, 10) >+absoluteChildContainer[1]: (8, 162, 784, 10) >+absoluteChildContainer[2]: (8, 162, 784, 10) >+absoluteChildContainer[3]: (118, 300, 140, 10) >+absoluteChildContainer[4]: (118, 300, 140, 10) >+relativeChildContainer[0]: (8, 272, 784, 10) >+relativeChildContainer[1]: (8, 272, 784, 10) >+relativeChildContainer[2]: (8, 272, 784, 10) >+relativeChildContainer[3]: (128, 472, 140, 10) >+overhangingContainer[0]: (8, 362, 784, 10) >+overhangingContainer[1]: (8, 362, 110, 80) >+overhangingContainer[2]: (8, 362, 110, 80) >+transformedChildContainer[0]: (62, 421, 661, 32) >+transformedChildContainer[1]: (62, 421, 661, 32) >+transformedChildContainer[2]: (8, 432, 769, 10) >+continuation[0]: (108, 502, 100, 10) >+ >Index: LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects.html >=================================================================== >--- LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects.html (revision 0) >+++ LayoutTests/platform/chromium/fast/events/touch/compositor-touch-hit-rects.html (revision 0) >@@ -0,0 +1,200 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+#transformedChild { >+ -webkit-transform: rotate3d(0.2, 1, 0, 35grad); >+} >+#absoluteChild { >+ position: absolute; >+ top: 300px; >+} >+#relativeChild { >+ position: relative; >+ top: 200px; >+} >+#overhangingContainer { >+ height: 10px; >+} >+#overhangingFloatingChild { >+ width: 100px; >+ float: left; >+} >+#tests { >+ font: 10px Ahem; >+} >+</style> >+</head> >+<body> >+<p id="description">This tests verifies the hit test regions given to the compositor. It can only be run in DumpRenderTree. >+The outputted rects should cover the hit test regions of all the listed elements.</p> >+<div id="console"></div> >+ >+<div id="tests"> >+ <div id="normalFlow"> >+ Lorem ipsum >+ <span>sum</span>. >+ </div> >+ <div id="absoluteChildContainer"> >+ Lorem ipsum >+ <span id="absoluteChild">Absolute child</span> >+ </div> >+ <div id="relativeChildContainer"> >+ Lorem ipsum >+ <span id="relativeChild">Relative child</span> >+ </div> >+ <div id="overhangingContainer"> >+ <div id="overhangingFloatingChild">Overhanging float overhanging float overhanging float overhanging float</div> >+ </div> >+ <div id="transformedChildContainer"> >+ <div id="transformedChild">Transformed</div> >+ </div> >+ <div> >+ <b id="continuation">This b tag >+ <div>causes a</div> >+ continuation</b> >+ </div> >+</div> >+<script> >+if (!window.testRunner) >+ return; >+ >+window.testRunner.dumpAsText(); >+ >+function listener() { } >+ >+function log(msg) { >+ var span = document.createElement("span"); >+ document.getElementById("console").appendChild(span); >+ span.innerHTML = msg + '<br />'; >+} >+ >+function sortRects(a, b) { >+ return a.top - b.top; >+} >+ >+function logRects(id) { >+ element = document.getElementById(id); >+ element.addEventListener('touchstart', listener, false); >+ rects = window.internals.touchEventTargetClientRects(document); >+ var sortedRects = new Array(); >+ for (var i = 0; i < rects.length; ++i) >+ sortedRects[i] = rects[i]; >+ sortedRects.sort(sortRects); >+ for (var i = 0; i < rects.length; ++i) >+ log(id + "[" + i + "]: (" + sortedRects[i].left + ", " + sortedRects[i].top + ", " + sortedRects[i].width + ", " + sortedRects[i].height + ")"); >+ element.removeEventListener('touchstart', listener, false); >+} >+ >+logRects("normalFlow"); >+logRects("absoluteChildContainer"); >+logRects("relativeChildContainer"); >+logRects("overhangingContainer"); >+logRects("transformedChildContainer"); >+logRects("continuation"); >+ >+var testContainer = document.getElementById("tests"); >+testContainer.parentNode.removeChild(testContainer); >+ >+</script> >+</body> >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+#transformedChild { >+ -webkit-transform: rotate3d(0.2, 1, 0, 35grad); >+} >+#absoluteChild { >+ position: absolute; >+ top: 300px; >+} >+#relativeChild { >+ position: relative; >+ top: 200px; >+} >+#overhangingContainer { >+ height: 10px; >+} >+#overhangingFloatingChild { >+ width: 100px; >+ float: left; >+} >+#tests { >+ font: 10px Ahem; >+} >+</style> >+</head> >+<body> >+<p id="description">This tests verifies the hit test regions given to the compositor. It can only be run in DumpRenderTree. >+The outputted rects should cover the hit test regions of all the listed elements.</p> >+<div id="console"></div> >+ >+<div id="tests"> >+ <div id="normalFlow"> >+ Lorem ipsum >+ <span>sum</span>. >+ </div> >+ <div id="absoluteChildContainer"> >+ Lorem ipsum >+ <span id="absoluteChild">Absolute child</span> >+ </div> >+ <div id="relativeChildContainer"> >+ Lorem ipsum >+ <span id="relativeChild">Relative child</span> >+ </div> >+ <div id="overhangingContainer"> >+ <div id="overhangingFloatingChild">Overhanging float overhanging float overhanging float overhanging float</div> >+ </div> >+ <div id="transformedChildContainer"> >+ <div id="transformedChild">Transformed</div> >+ </div> >+ <div> >+ <b id="continuation">This b tag >+ <div>causes a</div> >+ continuation</b> >+ </div> >+</div> >+<script> >+if (!window.testRunner) >+ return; >+ >+window.testRunner.dumpAsText(); >+ >+function listener() { } >+ >+function log(msg) { >+ var span = document.createElement("span"); >+ document.getElementById("console").appendChild(span); >+ span.innerHTML = msg + '<br />'; >+} >+ >+function sortRects(a, b) { >+ return a.top - b.top; >+} >+ >+function logRects(id) { >+ element = document.getElementById(id); >+ element.addEventListener('touchstart', listener, false); >+ rects = window.internals.touchEventTargetClientRects(document); >+ var sortedRects = new Array(); >+ for (var i = 0; i < rects.length; ++i) >+ sortedRects[i] = rects[i]; >+ sortedRects.sort(sortRects); >+ for (var i = 0; i < rects.length; ++i) >+ log(id + "[" + i + "]: (" + sortedRects[i].left + ", " + sortedRects[i].top + ", " + sortedRects[i].width + ", " + sortedRects[i].height + ")"); >+ element.removeEventListener('touchstart', listener, false); >+} >+ >+logRects("normalFlow"); >+logRects("absoluteChildContainer"); >+logRects("relativeChildContainer"); >+logRects("overhangingContainer"); >+logRects("transformedChildContainer"); >+logRects("continuation"); >+ >+var testContainer = document.getElementById("tests"); >+testContainer.parentNode.removeChild(testContainer); >+ >+</script> >+</body> >Index: LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash-expected.txt >=================================================================== >--- LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash-expected.txt (revision 0) >+++ LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash-expected.txt (revision 0) >@@ -0,0 +1 @@ >+Test passes if no crash. >Index: LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash.html >=================================================================== >--- LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash.html (revision 0) >+++ LayoutTests/platform/chromium/fast/events/touch/touch-target-removed-crash.html (revision 0) >@@ -0,0 +1,25 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<p id="description">Test passes if no crash.</p> >+<script> >+if (!window.testRunner) >+ return; >+ >+window.testRunner.dumpAsText(); >+ >+function crash() { >+ var div = document.createElement('div'); >+ div.ontouchstart = function() { }; >+ document.body.appendChild(div); >+ window.internals.touchEventHandlerCount(document); >+ div.parentNode.removeChild(div); >+ div = 0; >+ if (window.GCController) >+ GCController.collect(); >+ window.internals.touchEventHandlerCount(document); >+} >+ >+crash(); >+</script> >+</body>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 103914
:
177303
|
177386
|
177507
|
177569
|
177615
|
178256
|
178272
|
178281
|
178580
|
178845
|
178874
|
179143
|
179146
|
179150
|
179565
| 179682