Changeset 137939 in webkit


Ignore:
Timestamp:
Dec 17, 2012, 1:42:25 PM (12 years ago)
Author:
leviw@chromium.org
Message:

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 James Robinson.

Source/WebCore:

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:

Source/WebKit/chromium:

Enabling touch event target region tracking.

  • features.gypi:
  • src/WebPluginContainerImpl.cpp:

(WebKit::WebPluginContainerImpl::requestTouchEventType):
(WebKit::WebPluginContainerImpl::~WebPluginContainerImpl):

LayoutTests:

  • 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.
Location:
trunk
Files:
4 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r137930 r137939  
     12012-12-17  Levi Weintraub  <leviw@chromium.org>
     2
     3        Add support for tracking hit test rectangles to enable fast event rejection in the compositor
     4        https://bugs.webkit.org/show_bug.cgi?id=103914
     5
     6        Reviewed by James Robinson.
     7
     8        * platform/chromium/fast/events/touch/compositor-touch-hit-rects-expected.txt: Added.
     9        * platform/chromium/fast/events/touch/compositor-touch-hit-rects.html: Added.
     10        * platform/chromium/fast/events/touch/touch-target-removed-crash-expected.txt: Added.
     11        * platform/chromium/fast/events/touch/touch-target-removed-crash.html: Added.
     12
    1132012-12-17  Bem Jones-Bey  <bjonesbe@adobe.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r137934 r137939  
     12012-12-17  Levi Weintraub  <leviw@chromium.org>
     2
     3        Add support for tracking hit test rectangles to enable fast event rejection in the compositor
     4        https://bugs.webkit.org/show_bug.cgi?id=103914
     5
     6        Reviewed by James Robinson.
     7
     8        Adding support for tracking hit test target regions for the purpose of performing initial hit testing
     9        in the compositor to avoid blocking scrolling on the main thread while waiting to hit test events that
     10        aren't occuring in regions with handlers. This is initially being done to avoid having to go to the main
     11        thread when scrolling by flicking on touch devices when the flick occurs outside a tracked touch event
     12        region. This patch includes the implementation to turn this on in Chromium.
     13
     14        To accomplish this goal, Document will now keep a counted hash set of nodes with touch event handlers
     15        instead of only an unsigned integer of the total count. ScrollingCoordinator then updates the compositor
     16        when new touch event handlers are registered or removed, or after layout much like how
     17        nonFastScrollableRegions are currently tracked.
     18
     19        This implementation will not properly update the hit test rects when the renderers are inside a sub-
     20        tree that scrolls.
     21
     22        This change was initially rolled out due to stale Node pointers in Document's touchEventTargets. This
     23        patch adds a callback to remove the Node from that structure to Node's destructor. This is covered
     24        by the touch-target-removed-crash.html test case which is also added.
     25
     26        Test: platform/chromium/fast/events/touch/compositor-touch-hit-rects.html
     27              platform/chromium/fast/events/touch/touch-target-removed-crash.html
     28
     29        * dom/Document.cpp:
     30        (WebCore::Document::Document): Added a HashCountedSet of touch target nodes. Note: DOMWindow targets
     31        are stored as the Document they point to.
     32        (WebCore::Document::didAddTouchEventHandler): Changed to keep track of the handler instead of a count, and
     33        to update the ScrollingCoordinator with the change.
     34        (WebCore::Document::didRemoveTouchEventHandler): Ditto.
     35        * dom/Document.h:
     36        (WebCore::Document::hasTouchEventHandlers): It's no longer O(1) to get the count of touch handlers, so
     37        expose whether there are any or not.
     38        (WebCore::Document::touchEventTargets):
     39        * dom/Node.cpp:
     40        (WebCore::Node::didMoveToNewDocument):
     41        (WebCore::tryAddEventListener):
     42        (WebCore::tryRemoveEventListener):
     43        * history/CachedFrame.cpp:
     44        (WebCore::CachedFrameBase::restore):
     45        * html/HTMLInputElement.cpp:
     46        (WebCore::HTMLInputElement::~HTMLInputElement):
     47        (WebCore::HTMLInputElement::updateType):
     48        * page/DOMWindow.cpp:
     49        (WebCore::DOMWindow::addEventListener): Add the Document to the touch target set instead of DOMWindow.
     50        (WebCore::DOMWindow::removeEventListener):
     51        * page/EventHandler.cpp:
     52        (WebCore::EventHandler::handleTouchEvent):
     53        * page/Frame.cpp:
     54        (WebCore::Frame::setDocument):
     55        * page/scrolling/ScrollingCoordinator.cpp:
     56        (WebCore::ScrollingCoordinator::computeAbsoluteTouchEventTargetRects): Walk the renderers for event handler
     57        nodes and generate the absolute hit testing rects.
     58        * page/scrolling/ScrollingCoordinator.h:
     59        (WebCore::ScrollingCoordinator::setTouchEventTargetRectsChanged): Hook to pass along the hit test rects to
     60        the scrolling tree/compositor.
     61        (ScrollingCoordinator):
     62        * page/scrolling/chromium/ScrollingCoordinatorChromium.cpp:
     63        (WebCore::ScrollingCoordinatorChromium::frameViewLayoutUpdated):
     64        (WebCore::ScrollingCoordinatorChromium::setTouchEventTargetRectsChanged):
     65        (WebCore::ScrollingCoordinatorChromium::setNonFastScrollableRegion):
     66        (WebCore::ScrollingCoordinatorChromium::setTouchEventTargetRects):
     67        * page/scrolling/chromium/ScrollingCoordinatorChromium.h:
     68        (ScrollingCoordinatorChromium):
     69        * testing/Internals.cpp:
     70        (WebCore::Internals::touchEventHandlerCount): Changed to do the work to calculate the actual count since
     71        it's no longer stored as an int in Document.
     72        (WebCore::Internals::touchEventTargetClientRects):
     73        * testing/Internals.h:
     74        (Internals):
     75        * testing/Internals.idl:
     76
    1772012-12-17  Avi Drissman  <avi@chromium.org>
    278
  • trunk/Source/WebCore/dom/Document.cpp

    r137761 r137939  
    499499    , m_writeRecursionDepth(0)
    500500    , m_wheelEventHandlerCount(0)
    501 #if ENABLE(TOUCH_EVENTS)
    502     , m_touchEventHandlerCount(0)
    503 #endif
    504501    , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
    505502    , m_scheduledTasksAreSuspended(false)
     
    614611    ASSERT(!m_guardRefCount);
    615612
     613#if ENABLE(TOUCH_EVENT_TRACKING)
     614    if (Document* ownerDocument = this->ownerDocument())
     615        ownerDocument->didRemoveEventTargetNode(this);
     616#endif
    616617    // FIXME: Should we reset m_domWindow when we detach from the Frame?
    617618    if (m_domWindow)
     
    56005601}
    56015602
    5602 void Document::didAddTouchEventHandler()
     5603void Document::didAddTouchEventHandler(Node* handler)
    56035604{
    56045605#if ENABLE(TOUCH_EVENTS)
    5605     ++m_touchEventHandlerCount;
    5606     if (m_touchEventHandlerCount > 1)
    5607         return;
    5608     if (Page* page = this->page())
    5609         page->chrome()->client()->needTouchEvents(true);
    5610 #endif
    5611 }
    5612 
    5613 void Document::didRemoveTouchEventHandler()
     5606    if (!m_touchEventTargets.get())
     5607        m_touchEventTargets = adoptPtr(new TouchEventTargetSet);
     5608    m_touchEventTargets->add(handler);
     5609    if (Document* parent = parentDocument()) {
     5610        parent->didAddTouchEventHandler(this);
     5611        return;
     5612    }
     5613    if (Page* page = this->page()) {
     5614#if ENABLE(TOUCH_EVENT_TRACKING)
     5615        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
     5616            scrollingCoordinator->touchEventTargetRectsDidChange(this);
     5617#endif
     5618        if (m_touchEventTargets->size() == 1)
     5619            page->chrome()->client()->needTouchEvents(true);
     5620    }
     5621#else
     5622    UNUSED_PARAM(handler);
     5623#endif
     5624}
     5625
     5626void Document::didRemoveTouchEventHandler(Node* handler)
    56145627{
    56155628#if ENABLE(TOUCH_EVENTS)
    5616     ASSERT(m_touchEventHandlerCount);
    5617     --m_touchEventHandlerCount;
    5618     if (m_touchEventHandlerCount)
    5619         return;
     5629    if (!m_touchEventTargets.get())
     5630        return;
     5631    ASSERT(m_touchEventTargets->contains(handler));
     5632    m_touchEventTargets->remove(handler);
     5633    if (Document* parent = parentDocument()) {
     5634        parent->didRemoveTouchEventHandler(this);
     5635        return;
     5636    }
    56205637
    56215638    Page* page = this->page();
    56225639    if (!page)
    56235640        return;
     5641#if ENABLE(TOUCH_EVENT_TRACKING)
     5642    if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
     5643        scrollingCoordinator->touchEventTargetRectsDidChange(this);
     5644#endif
     5645    if (m_touchEventTargets->size())
     5646        return;
    56245647    for (const Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
    5625         if (frame->document() && frame->document()->touchEventHandlerCount())
     5648        if (frame->document() && frame->document()->hasTouchEventHandlers())
    56265649            return;
    56275650    }
    56285651    page->chrome()->client()->needTouchEvents(false);
    5629 #endif
    5630 }
     5652#else
     5653    UNUSED_PARAM(handler);
     5654#endif
     5655}
     5656
     5657#if ENABLE(TOUCH_EVENT_TRACKING)
     5658void Document::didRemoveEventTargetNode(Node* handler)
     5659{
     5660    if (m_touchEventTargets.get())
     5661        m_touchEventTargets->removeAll(handler);
     5662}
     5663#endif
    56315664
    56325665HTMLIFrameElement* Document::seamlessParentIFrame() const
  • trunk/Source/WebCore/dom/Document.h

    r137761 r137939  
    208208const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1;
    209209
     210typedef HashCountedSet<Node*> TouchEventTargetSet;
     211
    210212class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
    211213public:
     
    11191121
    11201122#if ENABLE(TOUCH_EVENTS)
    1121     unsigned touchEventHandlerCount() const { return m_touchEventHandlerCount; }
     1123    bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; }
    11221124#else
    1123     unsigned touchEventHandlerCount() const { return 0; }
    1124 #endif
    1125 
    1126     void didAddTouchEventHandler();
    1127     void didRemoveTouchEventHandler();
     1125    bool hasTouchEventHandlers() const { return false; }
     1126#endif
     1127
     1128    void didAddTouchEventHandler(Node*);
     1129    void didRemoveTouchEventHandler(Node*);
     1130
     1131#if ENABLE(TOUCH_EVENT_TRACKING)
     1132    void didRemoveEventTargetNode(Node*);
     1133#endif
     1134
     1135#if ENABLE(TOUCH_EVENTS)
     1136    const TouchEventTargetSet* touchEventTargets() const { return m_touchEventTargets.get(); }
     1137#else
     1138    const TouchEventTargetSet* touchEventTargets() const { return 0; }
     1139#endif
    11281140
    11291141    bool visualUpdatesAllowed() const { return m_visualUpdatesAllowed; }
     
    15041516    unsigned m_wheelEventHandlerCount;
    15051517#if ENABLE(TOUCH_EVENTS)
    1506     unsigned m_touchEventHandlerCount;
     1518    OwnPtr<TouchEventTargetSet> m_touchEventTargets;
    15071519#endif
    15081520
  • trunk/Source/WebCore/dom/Node.cpp

    r137761 r137939  
    413413        clearRareData();
    414414
    415     if (hasEventTargetData())
     415    if (hasEventTargetData()) {
     416#if ENABLE(TOUCH_EVENT_TRACKING)
     417        if (m_document)
     418            m_document->didRemoveEventTargetNode(this);
     419#endif
    416420        clearEventTargetData();
     421    }
    417422
    418423    if (renderer())
     
    21262131        const EventListenerVector& listeners = getEventListeners(touchEventNames[i]);
    21272132        for (size_t j = 0; j < listeners.size(); ++j) {
    2128             oldDocument->didRemoveTouchEventHandler();
    2129             document()->didAddTouchEventHandler();
     2133            oldDocument->didRemoveTouchEventHandler(this);
     2134            document()->didAddTouchEventHandler(this);
    21302135        }
    21312136    }
     
    21562161            document->didAddWheelEventHandler();
    21572162        else if (eventNames().isTouchEventType(eventType))
    2158             document->didAddTouchEventHandler();
     2163            document->didAddTouchEventHandler(targetNode);
    21592164    }
    21602165
     
    21782183            document->didRemoveWheelEventHandler();
    21792184        else if (eventNames().isTouchEventType(eventType))
    2180             document->didRemoveTouchEventHandler();
     2185            document->didRemoveTouchEventHandler(targetNode);
    21812186    }
    21822187
  • trunk/Source/WebCore/history/CachedFrame.cpp

    r137761 r137939  
    135135   
    136136#if ENABLE(TOUCH_EVENTS)
    137     if (m_document->touchEventHandlerCount())
     137    if (m_document->hasTouchEventHandlers())
    138138        m_document->page()->chrome()->client()->needTouchEvents(true);
    139139#endif
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r137761 r137939  
    164164#if ENABLE(TOUCH_EVENTS)
    165165    if (m_hasTouchEventHandler)
    166         document()->didRemoveTouchEventHandler();
     166        document()->didRemoveTouchEventHandler(this);
    167167#endif
    168168}
     
    490490    if (hasTouchEventHandler != m_hasTouchEventHandler) {
    491491      if (hasTouchEventHandler)
    492         document()->didAddTouchEventHandler();
     492        document()->didAddTouchEventHandler(this);
    493493      else
    494         document()->didRemoveTouchEventHandler();
     494        document()->didRemoveTouchEventHandler(this);
    495495      m_hasTouchEventHandler = hasTouchEventHandler;
    496496    }
  • trunk/Source/WebCore/page/DOMWindow.cpp

    r137776 r137939  
    15831583            document->didAddWheelEventHandler();
    15841584        else if (eventNames().isTouchEventType(eventType))
    1585             document->didAddTouchEventHandler();
     1585            document->didAddTouchEventHandler(document);
    15861586        else if (eventType == eventNames().storageEvent)
    15871587            didAddStorageEventListener(this);
     
    16141614            document->didRemoveWheelEventHandler();
    16151615        else if (eventNames().isTouchEventType(eventType))
    1616             document->didRemoveTouchEventHandler();
     1616            document->didRemoveTouchEventHandler(document);
    16171617    }
    16181618
  • trunk/Source/WebCore/page/EventHandler.cpp

    r137761 r137939  
    37703770            if (!doc)
    37713771                continue;
    3772             if (!doc->touchEventHandlerCount())
     3772            if (!doc->hasTouchEventHandlers())
    37733773                continue;
    37743774            m_originatingTouchPointTargets.set(touchPointTargetKey, node);
     
    37953795        if (!doc)
    37963796            continue;
    3797         if (!doc->touchEventHandlerCount())
     3797        if (!doc->hasTouchEventHandlers())
    37983798            continue;
    37993799        Frame* targetFrame = doc->frame();
  • trunk/Source/WebCore/page/Frame.cpp

    r137761 r137939  
    310310        notifyChromeClientWheelEventHandlerCountChanged();
    311311#if ENABLE(TOUCH_EVENTS)
    312         if (m_doc && m_doc->touchEventHandlerCount())
     312        if (m_doc && m_doc->hasTouchEventHandlers())
    313313            m_page->chrome()->client()->needTouchEvents(true);
    314314#endif
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp

    r137811 r137939  
    2828#include "ScrollingCoordinator.h"
    2929
     30#include "Document.h"
    3031#include "Frame.h"
    3132#include "FrameView.h"
     
    178179}
    179180
     181#if ENABLE(TOUCH_EVENT_TRACKING)
     182static void accumulateRendererTouchEventTargetRects(Vector<IntRect>& rects, const RenderObject* renderer)
     183{
     184    // FIXME: This method is O(N^2) as it walks the tree to the root for every renderer. RenderGeometryMap would fix this.
     185    rects.append(enclosingIntRect(renderer->clippedOverflowRectForRepaint(0)));
     186    if (renderer->isRenderBlock()) {
     187        const RenderBlock* block = toRenderBlock(renderer);
     188        for (RenderObject* child = block->firstChild(); child; child = child->nextSibling())
     189            accumulateRendererTouchEventTargetRects(rects, child);
     190    }
     191}
     192
     193static void accumulateDocumentEventTargetRects(Vector<IntRect>& rects, const Document* document)
     194{
     195    ASSERT(document);
     196    if (!document->touchEventTargets())
     197        return;
     198
     199    const TouchEventTargetSet* targets = document->touchEventTargets();
     200    for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
     201        const Node* touchTarget = iter->key;
     202        if (!touchTarget->inDocument())
     203            continue;
     204
     205        if (touchTarget == document) {
     206            if (RenderView* view = document->renderView())
     207                rects.append(enclosingIntRect(view->clippedOverflowRectForRepaint(0)));
     208            return;
     209        }
     210
     211        if (touchTarget->isDocumentNode() && touchTarget != document) {
     212            accumulateDocumentEventTargetRects(rects, static_cast<const Document*>(touchTarget));
     213            continue;
     214        }
     215
     216        if (RenderObject* renderer = touchTarget->renderer())
     217            accumulateRendererTouchEventTargetRects(rects, renderer);
     218    }
     219}
     220
     221void ScrollingCoordinator::computeAbsoluteTouchEventTargetRects(const Document* document, Vector<IntRect>& rects)
     222{
     223    ASSERT(document);
     224    if (!document->view())
     225        return;
     226
     227    // FIXME: These rects won't be properly updated if the renderers are in a sub-tree that scrolls.
     228    accumulateDocumentEventTargetRects(rects, document);
     229}
     230#endif
     231
    180232unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount()
    181233{
  • trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h

    r137761 r137939  
    3030#include "LayoutRect.h"
    3131#include "PlatformWheelEvent.h"
     32#include "RenderObject.h"
    3233#include "ScrollTypes.h"
    3334#include "Timer.h"
     
    5152enum ScrollingNodeType { ScrollingNode, FixedNode };
    5253
     54class Document;
    5355class Frame;
    5456class FrameView;
     
    150152    virtual void setLayerIsContainerForFixedPositionLayers(GraphicsLayer*, bool) { }
    151153    virtual void setLayerIsFixedToContainerLayer(GraphicsLayer*, bool) { }
     154    virtual void touchEventTargetRectsDidChange(const Document*) { }
     155
     156#if ENABLE(TOUCH_EVENT_TRACKING)
     157    void computeAbsoluteTouchEventTargetRects(const Document*, Vector<IntRect>&);
     158#endif
    152159
    153160    static String mainThreadScrollingReasonsAsText(MainThreadScrollingReasons);
  • trunk/Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.cpp

    r137761 r137939  
    116116    Region nonFastScrollableRegion = computeNonFastScrollableRegion(m_page->mainFrame(), IntPoint());
    117117    setNonFastScrollableRegion(nonFastScrollableRegion);
     118#if ENABLE(TOUCH_EVENT_TRACKING)
     119    Vector<IntRect> touchEventTargetRects;
     120    computeAbsoluteTouchEventTargetRects(m_page->mainFrame()->document(), touchEventTargetRects);
     121    setTouchEventTargetRects(touchEventTargetRects);
     122#endif
     123}
     124
     125void ScrollingCoordinatorChromium::touchEventTargetRectsDidChange(const Document* document)
     126{
     127#if ENABLE(TOUCH_EVENT_TRACKING)
     128    // Wait until after layout to update.
     129    if (m_page->mainFrame()->view()->needsLayout())
     130        return;
     131
     132    // We won't necessarily get a setScrollLayer() call before this one, so grab the root ourselves.
     133    setScrollLayer(scrollLayerForFrameView(m_page->mainFrame()->view()));
     134    if (m_private->scrollLayer()) {
     135        Vector<IntRect> touchEventTargetRects;
     136        computeAbsoluteTouchEventTargetRects(document, touchEventTargetRects);
     137        setTouchEventTargetRects(touchEventTargetRects);
     138    }
     139#else
     140    UNUSED_PARAM(document);
     141#endif
    118142}
    119143
     
    210234}
    211235
     236void ScrollingCoordinatorChromium::setTouchEventTargetRects(const Vector<IntRect>& absoluteHitTestRects)
     237{
     238    // We won't necessarily get a setScrollLayer() call before this one, so grab the root ourselves.
     239    setScrollLayer(scrollLayerForFrameView(m_page->mainFrame()->view()));
     240    if (m_private->scrollLayer()) {
     241        WebVector<WebRect> webRects(absoluteHitTestRects.size());
     242        for (size_t i = 0; i < absoluteHitTestRects.size(); ++i)
     243            webRects[i] = absoluteHitTestRects[i];
     244        m_private->scrollLayer()->setTouchEventHandlerRegion(webRects);
     245    }
     246}
     247
    212248void ScrollingCoordinatorChromium::setWheelEventHandlerCount(unsigned wheelEventHandlerCount)
    213249{
  • trunk/Source/WebCore/page/scrolling/chromium/ScrollingCoordinatorChromium.h

    r137761 r137939  
    6969    virtual void scrollableAreaScrollLayerDidChange(ScrollableArea*, GraphicsLayer*);
    7070
     71    // Should be called whenever touch handlers are registered, removed, or moved.
     72    virtual void touchEventTargetRectsDidChange(const Document*) OVERRIDE;
     73
    7174private:
    7275    virtual void recomputeWheelEventHandlerCountForFrameView(FrameView*);
     
    7578    void setScrollLayer(GraphicsLayer*);
    7679    void setNonFastScrollableRegion(const Region&);
     80    void setTouchEventTargetRects(const Vector<IntRect>&);
    7781    void setWheelEventHandlerCount(unsigned);
    7882    PassOwnPtr<WebKit::WebScrollbarLayer> createScrollbarLayer(Scrollbar*, WebKit::WebLayer* scrollLayer, GraphicsLayer* scrollbarGraphicsLayer, FrameView*);
  • trunk/Source/WebCore/testing/Internals.cpp

    r137761 r137939  
    7474#include "RuntimeEnabledFeatures.h"
    7575#include "SchemeRegistry.h"
     76#include "ScrollingCoordinator.h"
    7677#include "SelectRuleFeatureSet.h"
    7778#include "SerializedScriptValue.h"
     
    12011202    }
    12021203
    1203     return document->touchEventHandlerCount();
    1204 }
     1204    const TouchEventTargetSet* touchHandlers = document->touchEventTargets();
     1205    if (!touchHandlers)
     1206        return 0;
     1207
     1208    unsigned count = 0;
     1209    for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter)
     1210        count += iter->value;
     1211    return count;
     1212}
     1213
     1214#if ENABLE(TOUCH_EVENT_TRACKING)
     1215PassRefPtr<ClientRectList> Internals::touchEventTargetClientRects(Document* document, ExceptionCode& ec)
     1216{
     1217    if (!document || !document->view() || !document->page()) {
     1218        ec = INVALID_ACCESS_ERR;
     1219        return 0;
     1220    }
     1221    if (!document->page()->scrollingCoordinator())
     1222        return ClientRectList::create();
     1223
     1224    document->updateLayoutIgnorePendingStylesheets();
     1225
     1226    Vector<IntRect> absoluteRects;
     1227    document->page()->scrollingCoordinator()->computeAbsoluteTouchEventTargetRects(document, absoluteRects);
     1228    Vector<FloatQuad> absoluteQuads(absoluteRects.size());
     1229
     1230    for (size_t i = 0; i < absoluteRects.size(); ++i)
     1231        absoluteQuads[i] = FloatQuad(absoluteRects[i]);
     1232
     1233    return ClientRectList::create(absoluteQuads);
     1234}
     1235#endif
    12051236
    12061237PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int x, int y, unsigned topPadding, unsigned rightPadding,
  • trunk/Source/WebCore/testing/Internals.h

    r137761 r137939  
    172172    unsigned wheelEventHandlerCount(Document*, ExceptionCode&);
    173173    unsigned touchEventHandlerCount(Document*, ExceptionCode&);
     174#if ENABLE(TOUCH_EVENT_TRACKING)
     175    PassRefPtr<ClientRectList> touchEventTargetClientRects(Document*, ExceptionCode&);
     176#endif
    174177
    175178    PassRefPtr<NodeList> nodesFromRect(Document*, int x, int y, unsigned topPadding, unsigned rightPadding,
  • trunk/Source/WebCore/testing/Internals.idl

    r137761 r137939  
    140140    unsigned long wheelEventHandlerCount(in Document document) raises (DOMException);
    141141    unsigned long touchEventHandlerCount(in Document document) raises (DOMException);
     142#if defined(ENABLE_TOUCH_EVENT_TRACKING) && ENABLE_TOUCH_EVENT_TRACKING
     143    ClientRectList touchEventTargetClientRects(in Document document) raises (DOMException);
     144#endif
    142145
    143146    NodeList nodesFromRect(in Document document, in long x, in long y,
  • trunk/Source/WebKit/chromium/ChangeLog

    r137921 r137939  
     12012-12-17  Levi Weintraub  <leviw@chromium.org>
     2
     3        Add support for tracking hit test rectangles to enable fast event rejection in the compositor
     4        https://bugs.webkit.org/show_bug.cgi?id=103914
     5
     6        Reviewed by James Robinson.
     7
     8        Enabling touch event target region tracking.
     9
     10        * features.gypi:
     11        * src/WebPluginContainerImpl.cpp:
     12        (WebKit::WebPluginContainerImpl::requestTouchEventType):
     13        (WebKit::WebPluginContainerImpl::~WebPluginContainerImpl):
     14
    1152012-12-17  James Robinson  <jamesr@chromium.org>
    216
  • trunk/Source/WebKit/chromium/features.gypi

    r137761 r137939  
    117117      'ENABLE_TOUCH_EVENTS=<(enable_touch_events)',
    118118      'ENABLE_TOUCH_ICON_LOADING=<(enable_touch_icon_loading)',
     119      'ENABLE_TOUCH_EVENT_TRACKING=<(enable_touch_events)',
    119120      'ENABLE_TOUCH_SLIDER=1',
    120121      'ENABLE_USER_TIMING=1',
  • trunk/Source/WebKit/chromium/src/WebPluginContainerImpl.cpp

    r137847 r137939  
    528528    m_touchEventRequestType = requestType;
    529529    if (m_touchEventRequestType != TouchEventRequestTypeNone)
    530         m_element->document()->didAddTouchEventHandler();
     530        m_element->document()->didAddTouchEventHandler(m_element);
    531531    else
    532         m_element->document()->didRemoveTouchEventHandler();
     532        m_element->document()->didRemoveTouchEventHandler(m_element);
    533533}
    534534
     
    673673{
    674674    if (m_touchEventRequestType != TouchEventRequestTypeNone)
    675         m_element->document()->didRemoveTouchEventHandler();
     675        m_element->document()->didRemoveTouchEventHandler(m_element);
    676676
    677677    for (size_t i = 0; i < m_pluginLoadObservers.size(); ++i)
Note: See TracChangeset for help on using the changeset viewer.