Title: [132279] trunk/Source/WebKit/blackberry
Revision
132279
Author
commit-qu...@webkit.org
Date
2012-10-23 16:10:50 -0700 (Tue, 23 Oct 2012)

Log Message

[BlackBerry] Cache TouchDown HitTestResult to avoid calling RenderLayer::hitTest unnecessarily
https://bugs.webkit.org/show_bug.cgi?id=99649

Patch by Mike Lattanzio <mlattan...@rim.com> on 2012-10-23
Reviewed by George Staikos.

Random latency before scroll starts on sites like http://pintrest.com
Internal PR225398

The chief problem here is the all the hit testing that we do for
touch events and simulated mouse events. If the render tree is dirty
hit tests can take a long time in Document::recalcStyle(). Masking
the flags that force style recalculations will make them fast, at the
expense that they might be happening on stale data.

Since we are only using these hit tests to look for event handlers -
we're not actually modifying anything, it is better to skip the
Document::recalcStyle() and save ourselves tons of time.

* Api/InRegionScroller.cpp:
(BlackBerry::WebKit::InRegionScrollerPrivate::calculateInRegionScrollableAreasForPoint):
* Api/WebPage.cpp:
(BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
(BlackBerry::WebKit::WebPage::touchEvent):
(BlackBerry::WebKit::WebPagePrivate::setScrollOriginPoint):
(BlackBerry::WebKit::WebPagePrivate::postponeDocumentStyleRecalc):
(WebKit):
(BlackBerry::WebKit::WebPagePrivate::resumeDocumentStyleRecalc):
(BlackBerry::WebKit::WebPagePrivate::hitTestResult):
(BlackBerry::WebKit::WebPagePrivate::clearCachedHitTestResult):
* Api/WebPage_p.h:
(WebPagePrivate):
* WebKitSupport/FatFingers.cpp:
(BlackBerry::WebKit::FatFingers::findBestPoint):
(BlackBerry::WebKit::FatFingers::getRelevantInfoFromCachedHitTest):
* WebKitSupport/FatFingers.h:
* WebKitSupport/TouchEventHandler.cpp:
(BlackBerry::WebKit::TouchEventHandler::handleTouchPoint):

Modified Paths

Diff

Modified: trunk/Source/WebKit/blackberry/Api/InRegionScroller.cpp (132278 => 132279)


--- trunk/Source/WebKit/blackberry/Api/InRegionScroller.cpp	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/Api/InRegionScroller.cpp	2012-10-23 23:10:50 UTC (rev 132279)
@@ -202,7 +202,7 @@
     ASSERT(m_activeInRegionScrollableAreas.empty());
     m_needsActiveScrollableAreaCalculation = false;
 
-    HitTestResult result = m_webPage->m_mainFrame->eventHandler()->hitTestResultAtPoint(m_webPage->mapFromViewportToContents(point));
+    const HitTestResult& result = m_webPage->hitTestResult(m_webPage->mapFromViewportToContents(point));
     Node* node = result.innerNonSharedNode();
     if (!node || !node->renderer())
         return;

Modified: trunk/Source/WebKit/blackberry/Api/WebPage.cpp (132278 => 132279)


--- trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-10-23 23:10:50 UTC (rev 132279)
@@ -432,6 +432,8 @@
     , m_deferredTasksTimer(this, &WebPagePrivate::deferredTasksTimerFired)
     , m_selectPopup(0)
     , m_autofillManager(AutofillManager::create(this))
+    , m_documentStyleRecalcPostponed(false)
+    , m_documentChildNeedsStyleRecalc(false)
 {
     static bool isInitialized = false;
     if (!isInitialized) {
@@ -441,6 +443,7 @@
     }
 
     AuthenticationChallengeManager::instance()->pageCreated(this);
+    clearCachedHitTestResult();
 }
 
 WebPage::WebPage(WebPageClient* client, const BlackBerry::Platform::String& pageGroupName, const Platform::IntRect& rect)
@@ -4074,6 +4077,9 @@
     else if (tEvent.m_type == Platform::TouchEvent::TouchStart || tEvent.m_type == Platform::TouchEvent::TouchCancel)
         d->m_pluginMayOpenNewTab = false;
 
+    if (tEvent.m_type == Platform::TouchEvent::TouchStart)
+        d->clearCachedHitTestResult();
+
     bool handled = false;
 
     if (d->m_needTouchEvents && !event.hasGesture(Platform::Gesture::Injected))
@@ -4110,9 +4116,11 @@
     if (!m_hasInRegionScrollableAreas)
         return;
 
+    postponeDocumentStyleRecalc();
     m_inRegionScroller->d->calculateInRegionScrollableAreasForPoint(point);
     if (!m_inRegionScroller->d->activeInRegionScrollableAreas().empty())
         m_client->notifyInRegionScrollableAreasChanged(m_inRegionScroller->d->activeInRegionScrollableAreas());
+    resumeDocumentStyleRecalc();
 }
 
 void WebPage::setScrollOriginPoint(const Platform::IntPoint& point)
@@ -6327,5 +6335,45 @@
     return Platform::Graphics::Screen::primaryScreen()->size();
 }
 
+bool WebPagePrivate::postponeDocumentStyleRecalc()
+{
+    if (Document* document = m_mainFrame->document()) {
+        m_documentChildNeedsStyleRecalc = document->childNeedsStyleRecalc();
+        document->clearChildNeedsStyleRecalc();
+
+        m_documentStyleRecalcPostponed = document->isPendingStyleRecalc();
+        document->unscheduleStyleRecalc();
+    }
 }
+
+void WebPagePrivate::resumeDocumentStyleRecalc()
+{
+    if (Document* document = m_mainFrame->document()) {
+        if (m_documentChildNeedsStyleRecalc)
+            document->setChildNeedsStyleRecalc();
+
+        if (m_documentStyleRecalcPostponed)
+            document->scheduleStyleRecalc();
+    }
+
+    m_documentChildNeedsStyleRecalc = false;
+    m_documentStyleRecalcPostponed = false;
 }
+
+const HitTestResult& WebPagePrivate::hitTestResult(const IntPoint& contentPos)
+{
+    if (m_cachedHitTestContentPos != contentPos) {
+        m_cachedHitTestContentPos = contentPos;
+        m_cachedHitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(m_cachedHitTestContentPos, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowShadowContent);
+    }
+
+    return m_cachedHitTestResult;
+}
+
+void WebPagePrivate::clearCachedHitTestResult()
+{
+    m_cachedHitTestContentPos = WebCore::IntPoint(-1, -1);
+}
+
+}
+}

Modified: trunk/Source/WebKit/blackberry/Api/WebPage_p.h (132278 => 132279)


--- trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-10-23 23:10:50 UTC (rev 132279)
@@ -20,6 +20,7 @@
 #define WebPage_p_h
 
 #include "ChromeClient.h"
+#include "HitTestResult.h"
 #include "InRegionScroller.h"
 #include "InspectorClientBlackBerry.h"
 #include "InspectorOverlay.h"
@@ -460,6 +461,12 @@
     void applySizeOverride(int overrideWidth, int overrideHeight);
     void setTextZoomFactor(float);
 
+    bool postponeDocumentStyleRecalc();
+    void resumeDocumentStyleRecalc();
+
+    const WebCore::HitTestResult& hitTestResult(const WebCore::IntPoint& contentPos);
+    void clearCachedHitTestResult();
+
     WebCore::IntSize screenSize() const;
 
     WebPage* m_webPage;
@@ -637,6 +644,12 @@
     WebCore::PagePopupBlackBerry* m_selectPopup;
 
     RefPtr<WebCore::AutofillManager> m_autofillManager;
+
+    bool m_documentStyleRecalcPostponed;
+    bool m_documentChildNeedsStyleRecalc;
+
+    WebCore::IntPoint m_cachedHitTestContentPos;
+    WebCore::HitTestResult m_cachedHitTestResult;
 protected:
     virtual ~WebPagePrivate();
 };

Modified: trunk/Source/WebKit/blackberry/ChangeLog (132278 => 132279)


--- trunk/Source/WebKit/blackberry/ChangeLog	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/ChangeLog	2012-10-23 23:10:50 UTC (rev 132279)
@@ -1,3 +1,43 @@
+2012-10-23  Mike Lattanzio  <mlattan...@rim.com>
+
+        [BlackBerry] Cache TouchDown HitTestResult to avoid calling RenderLayer::hitTest unnecessarily
+        https://bugs.webkit.org/show_bug.cgi?id=99649
+
+        Reviewed by George Staikos.
+
+        Random latency before scroll starts on sites like http://pintrest.com
+        Internal PR225398
+
+        The chief problem here is the all the hit testing that we do for
+        touch events and simulated mouse events. If the render tree is dirty
+        hit tests can take a long time in Document::recalcStyle(). Masking
+        the flags that force style recalculations will make them fast, at the
+        expense that they might be happening on stale data.
+
+        Since we are only using these hit tests to look for event handlers -
+        we're not actually modifying anything, it is better to skip the
+        Document::recalcStyle() and save ourselves tons of time.
+
+        * Api/InRegionScroller.cpp:
+        (BlackBerry::WebKit::InRegionScrollerPrivate::calculateInRegionScrollableAreasForPoint):
+        * Api/WebPage.cpp:
+        (BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
+        (BlackBerry::WebKit::WebPage::touchEvent):
+        (BlackBerry::WebKit::WebPagePrivate::setScrollOriginPoint):
+        (BlackBerry::WebKit::WebPagePrivate::postponeDocumentStyleRecalc):
+        (WebKit):
+        (BlackBerry::WebKit::WebPagePrivate::resumeDocumentStyleRecalc):
+        (BlackBerry::WebKit::WebPagePrivate::hitTestResult):
+        (BlackBerry::WebKit::WebPagePrivate::clearCachedHitTestResult):
+        * Api/WebPage_p.h:
+        (WebPagePrivate):
+        * WebKitSupport/FatFingers.cpp:
+        (BlackBerry::WebKit::FatFingers::findBestPoint):
+        (BlackBerry::WebKit::FatFingers::getRelevantInfoFromCachedHitTest):
+        * WebKitSupport/FatFingers.h:
+        * WebKitSupport/TouchEventHandler.cpp:
+        (BlackBerry::WebKit::TouchEventHandler::handleTouchPoint):
+
 2012-10-23  Rob Buis  <rb...@rim.com>
 
         [BlackBerry] Make selection in search input box not overlap cancel button

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp (132278 => 132279)


--- trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp	2012-10-23 23:10:50 UTC (rev 132279)
@@ -181,7 +181,7 @@
     // targable is actually found by ::findIntersectingRegions, then we might replace what we just set below later on.
     Element* elementUnderPoint;
     Element* clickableElementUnderPoint;
-    getRelevantInfoFromPoint(m_webPage->m_mainFrame->document(), m_contentPos, elementUnderPoint, clickableElementUnderPoint);
+    getRelevantInfoFromCachedHitTest(elementUnderPoint, clickableElementUnderPoint);
 
     if (elementUnderPoint) {
         result.m_nodeUnderFatFinger = elementUnderPoint;
@@ -500,15 +500,12 @@
     m_cachedRectHitTestResults.add(document, intersectedNodes);
 }
 
-void FatFingers::getRelevantInfoFromPoint(Document* document, const IntPoint& contentPos, Element*& elementUnderPoint, Element*& clickableElementUnderPoint) const
+void FatFingers::getRelevantInfoFromCachedHitTest(Element*& elementUnderPoint, Element*& clickableElementUnderPoint) const
 {
     elementUnderPoint = 0;
     clickableElementUnderPoint = 0;
 
-    if (!document || !document->renderer() || !document->frame())
-        return;
-
-    HitTestResult result  = document->frame()->eventHandler()->hitTestResultAtPoint(contentPos, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowShadowContent);
+    const HitTestResult& result = m_webPage->hitTestResult(m_contentPos);
     Node* node = result.innerNode();
     while (node && !node->isElementNode())
         node = node->parentNode();

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.h (132278 => 132279)


--- trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.h	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/FatFingers.h	2012-10-23 23:10:50 UTC (rev 132279)
@@ -99,10 +99,7 @@
     void getNodesFromRect(WebCore::Document*, const WebCore::IntPoint&, ListHashSet<RefPtr<WebCore::Node> >&);
 
     // It mimics Document::elementFromPoint, but recursively hit-tests in case an inner frame is found.
-    void getRelevantInfoFromPoint(WebCore::Document*,
-                                  const WebCore::IntPoint&,
-                                  WebCore::Element*& elementUnderPoint,
-                                  WebCore::Element*& clickableElementUnderPoint) const;
+    void getRelevantInfoFromCachedHitTest(WebCore::Element*& elementUnderPoint, WebCore::Element*& clickableElementUnderPoint) const;
 
     bool isElementClickable(WebCore::Element*) const;
 

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp (132278 => 132279)


--- trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp	2012-10-23 22:46:22 UTC (rev 132278)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp	2012-10-23 23:10:50 UTC (rev 132279)
@@ -199,6 +199,7 @@
 
             IntPoint contentPos(m_webPage->mapFromViewportToContents(point.m_pos));
 
+            m_webPage->postponeDocumentStyleRecalc();
             m_lastFatFingersResult = FatFingers(m_webPage, contentPos, FatFingers::ClickableElement).findBestPoint();
 
             Element* elementUnderFatFinger = 0;
@@ -214,6 +215,8 @@
             if (!possibleTargetNodeForMouseMoveEvents || (!possibleTargetNodeForMouseMoveEvents->hasEventListeners(eventNames().touchmoveEvent) && !m_convertTouchToMouse))
                 m_webPage->client()->notifyNoMouseMoveOrTouchMoveHandlers();
 
+            m_webPage->resumeDocumentStyleRecalc();
+
             if (elementUnderFatFinger)
                 drawTapHighlight();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to