Title: [124470] trunk/Source/WebKit
Revision
124470
Author
[email protected]
Date
2012-08-02 09:42:13 -0700 (Thu, 02 Aug 2012)

Log Message

[BlackBerry] Implement InRegionScroller class as a in-region scroll controller
https://bugs.webkit.org/show_bug.cgi?id=92889
PR #186587

Reviewed by Yong Li.
Patch by Antonio Gomes <[email protected]>

Internally reviewed by Arvid Nilsson.

Source/WebKit:

* PlatformBlackBerry.cmake: Added InRegionScroller.cpp|h to the build system.

Source/WebKit/blackberry:

Moved all in-region scrolling code out of WebPagePrivate to the just
created InRegionScroller class. This class aims to:

1) Centralize all in-region scroll code and clean up WebPagePrivate as a consequence.
2) Be the bases to add UI/Compositing thread driven scrolls to in-region.

The patch does not change any functionallity change.

* Api/WebPage.cpp:
(BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
(BlackBerry::WebKit::WebPagePrivate::init):
(BlackBerry::WebKit::WebPagePrivate::scrollBy):
(BlackBerry::WebKit::WebPagePrivate::notifyInRegionScrollStatusChanged):
(BlackBerry::WebKit::WebPagePrivate::clearDocumentData):
(BlackBerry::WebKit::WebPagePrivate::setScrollOriginPoint):
* Api/WebPage_p.h:
(WebPagePrivate):
* WebKitSupport/InRegionScrollableArea.cpp:
(BlackBerry::WebKit::InRegionScrollableArea::layer):
* WebKitSupport/InRegionScroller.cpp: Added.
(WebKit):
(BlackBerry::WebKit::canScrollInnerFrame):
(BlackBerry::WebKit::canScrollRenderBox):
(BlackBerry::WebKit::parentLayer):
(BlackBerry::WebKit::enclosingLayerNode):
(BlackBerry::WebKit::isNonRenderViewFixedPositionedContainer):
(BlackBerry::WebKit::pushBackInRegionScrollable):
(BlackBerry::WebKit::InRegionScroller::InRegionScroller):
(BlackBerry::WebKit::InRegionScroller::setNode):
(BlackBerry::WebKit::InRegionScroller::node):
(BlackBerry::WebKit::InRegionScroller::reset):
(BlackBerry::WebKit::InRegionScroller::isNull):
(BlackBerry::WebKit::InRegionScroller::scrollBy):
(BlackBerry::WebKit::InRegionScroller::inRegionScrollableAreasForPoint):
(BlackBerry::WebKit::InRegionScroller::scrollNodeRecursively):
(BlackBerry::WebKit::InRegionScroller::scrollRenderer):
(BlackBerry::WebKit::InRegionScroller::adjustScrollDelta):
* WebKitSupport/InRegionScroller.h: Added.
(WebCore):
(WebKit):
(InRegionScroller):
* WebKitSupport/TouchEventHandler.cpp:
(BlackBerry::WebKit::TouchEventHandler::drawTapHighlight):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (124469 => 124470)


--- trunk/Source/WebKit/ChangeLog	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/ChangeLog	2012-08-02 16:42:13 UTC (rev 124470)
@@ -1,3 +1,15 @@
+2012-08-01  Antonio Gomes  <[email protected]>
+
+        [BlackBerry] Implement InRegionScroller class as a in-region scroll controller
+        https://bugs.webkit.org/show_bug.cgi?id=92889
+        PR #186587
+
+        Reviewed by Yong Li.
+
+        Internally reviewed by Arvid Nilsson.
+
+        * PlatformBlackBerry.cmake: Added InRegionScroller.cpp|h to the build system.
+
 2012-07-30  Simon Hausmann  <[email protected]>
 
         Unreviewed Qt/Mac build fix: Use libWebKitSystemInterfaceMountainLion.a

Modified: trunk/Source/WebKit/PlatformBlackBerry.cmake (124469 => 124470)


--- trunk/Source/WebKit/PlatformBlackBerry.cmake	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/PlatformBlackBerry.cmake	2012-08-02 16:42:13 UTC (rev 124470)
@@ -100,6 +100,8 @@
     blackberry/WebKitSupport/FrameLayers.cpp
     blackberry/WebKitSupport/InPageSearchManager.cpp
     blackberry/WebKitSupport/InputHandler.cpp
+    blackberry/WebKitSupport/InRegionScrollableArea.cpp
+    blackberry/WebKitSupport/InRegionScroller.cpp
     blackberry/WebKitSupport/RenderQueue.cpp
     blackberry/WebKitSupport/SelectionHandler.cpp
     blackberry/WebKitSupport/SelectionOverlay.cpp

Modified: trunk/Source/WebKit/blackberry/Api/WebPage.cpp (124469 => 124470)


--- trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-08-02 16:42:13 UTC (rev 124470)
@@ -393,7 +393,6 @@
     , m_lastUserEventTimestamp(0.0)
     , m_pluginMouseButtonPressed(false)
     , m_pluginMayOpenNewTab(false)
-    , m_inRegionScrollStartingNode(0)
 #if USE(ACCELERATED_COMPOSITING)
     , m_rootLayerCommitTimer(adoptPtr(new Timer<WebPagePrivate>(this, &WebPagePrivate::rootLayerCommitTimerFired)))
     , m_needsOneShotDrawingSynchronization(false)
@@ -558,6 +557,8 @@
     frameLoaderClient->setFrame(m_mainFrame, this);
     m_mainFrame->init();
 
+    m_inRegionScroller = adoptPtr(new InRegionScroller(this));
+
 #if ENABLE(WEBGL)
     Platform::Settings* settings = Platform::Settings::instance();
     m_page->settings()->setWebGLEnabled(settings && settings->isWebGLSupported());
@@ -1522,15 +1523,13 @@
             delta.width() < 0 ? -untransformedCopiedDelta.width() : untransformedCopiedDelta.width(),
             delta.height() < 0 ? -untransformedCopiedDelta.height(): untransformedCopiedDelta.height());
 
-        if (m_inRegionScrollStartingNode) {
-            if (scrollNodeRecursively(m_inRegionScrollStartingNode.get(), delta)) {
-                m_selectionHandler->selectionPositionChanged();
-                // FIXME: We have code in place to handle scrolling and clipping tap highlight
-                // on in-region scrolling. As soon as it is fast enough (i.e. we have it backed by
-                // a backing store), we can reliably make use of it in the real world.
-                // m_touchEventHandler->drawTapHighlight();
-                return true;
-            }
+        if (m_inRegionScroller->scrollBy(delta)) {
+            m_selectionHandler->selectionPositionChanged();
+            // FIXME: We have code in place to handle scrolling and clipping tap highlight
+            // on in-region scrolling. As soon as it is fast enough (i.e. we have it backed by
+            // a backing store), we can reliably make use of it in the real world.
+            // m_touchEventHandler->drawTapHighlight();
+            return true;
         }
 
         return false;
@@ -1550,9 +1549,9 @@
 
 void WebPagePrivate::notifyInRegionScrollStatusChanged(bool status)
 {
-    if (!status && m_inRegionScrollStartingNode) {
-        enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(m_inRegionScrollStartingNode.get());
-        m_inRegionScrollStartingNode = 0;
+    if (!status && m_inRegionScroller->hasNode()) {
+        enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(m_inRegionScroller->node());
+        m_inRegionScroller->reset();
     }
 }
 
@@ -2635,8 +2634,8 @@
     if (m_currentBlockZoomAdjustedNode && m_currentBlockZoomAdjustedNode->document() == documentGoingAway)
         m_currentBlockZoomAdjustedNode = 0;
 
-    if (m_inRegionScrollStartingNode && m_inRegionScrollStartingNode->document() == documentGoingAway)
-        m_inRegionScrollStartingNode = 0;
+    if (m_inRegionScroller->hasNode() && m_inRegionScroller->node()->document() == documentGoingAway)
+        m_inRegionScroller->reset();
 
     if (documentGoingAway->frame())
         m_inputHandler->frameUnloaded(documentGoingAway->frame());
@@ -2656,15 +2655,6 @@
     return o->isRenderView() || o->isOutOfFlowPositioned() || o->isRelPositioned() || layer->hasTransform();
 }
 
-static bool isNonRenderViewFixedPositionedContainer(RenderLayer* layer)
-{
-    RenderObject* o = layer->renderer();
-    if (o->isRenderView())
-        return false;
-
-    return o->isOutOfFlowPositioned() && o->style()->position() == FixedPosition;
-}
-
 static bool isFixedPositionedContainer(RenderLayer* layer)
 {
     RenderObject* o = layer->renderer();
@@ -4223,12 +4213,12 @@
 
 void WebPagePrivate::setScrollOriginPoint(const Platform::IntPoint& point)
 {
-    m_inRegionScrollStartingNode = 0;
+    m_inRegionScroller->reset();
 
     if (!m_hasInRegionScrollableAreas)
         return;
 
-    m_client->notifyInRegionScrollingStartingPointChanged(inRegionScrollableAreasForPoint(point));
+    m_client->notifyInRegionScrollingStartingPointChanged(m_inRegionScroller->inRegionScrollableAreasForPoint(point));
 }
 
 void WebPage::setScrollOriginPoint(const Platform::IntPoint& point)
@@ -4398,120 +4388,6 @@
         return d->focusedOrMainFrame()->loader()->reloadWithOverrideEncoding(encoding);
 }
 
-bool WebPagePrivate::scrollNodeRecursively(Node* node, const IntSize& delta)
-{
-    if (delta.isZero())
-        return true;
-
-    if (!node)
-        return false;
-
-    RenderObject* renderer = node->renderer();
-    if (!renderer)
-        return false;
-
-    FrameView* view = renderer->view()->frameView();
-    if (!view)
-        return false;
-
-    // Try scrolling the renderer.
-    if (scrollRenderer(renderer, delta))
-        return true;
-
-    // We've hit the page, don't scroll it and return false.
-    if (view == m_mainFrame->view())
-        return false;
-
-    // Try scrolling the FrameView.
-    if (canScrollInnerFrame(view->frame())) {
-        IntSize viewDelta = delta;
-        IntPoint newViewOffset = view->scrollPosition();
-        IntPoint maxViewOffset = view->maximumScrollPosition();
-        adjustScrollDelta(maxViewOffset, newViewOffset, viewDelta);
-
-        if (!viewDelta.isZero()) {
-            view->setCanBlitOnScroll(false);
-
-            BackingStoreClient* backingStoreClient = backingStoreClientForFrame(view->frame());
-            if (backingStoreClient) {
-                backingStoreClient->setIsClientGeneratedScroll(true);
-                backingStoreClient->setIsScrollNotificationSuppressed(true);
-            }
-
-            m_inRegionScrollStartingNode = view->frame()->document();
-
-            view->scrollBy(viewDelta);
-
-            if (backingStoreClient) {
-                backingStoreClient->setIsClientGeneratedScroll(false);
-                backingStoreClient->setIsScrollNotificationSuppressed(false);
-            }
-
-            return true;
-        }
-    }
-
-    // Try scrolling the node of the enclosing frame.
-    Frame* frame = node->document()->frame();
-    if (frame) {
-        Node* ownerNode = frame->ownerElement();
-        if (scrollNodeRecursively(ownerNode, delta))
-            return true;
-    }
-
-    return false;
-}
-
-void WebPagePrivate::adjustScrollDelta(const IntPoint& maxOffset, const IntPoint& currentOffset, IntSize& delta) const
-{
-    if (currentOffset.x() + delta.width() > maxOffset.x())
-        delta.setWidth(min(maxOffset.x() - currentOffset.x(), delta.width()));
-
-    if (currentOffset.x() + delta.width() < 0)
-        delta.setWidth(max(-currentOffset.x(), delta.width()));
-
-    if (currentOffset.y() + delta.height() > maxOffset.y())
-        delta.setHeight(min(maxOffset.y() - currentOffset.y(), delta.height()));
-
-    if (currentOffset.y() + delta.height() < 0)
-        delta.setHeight(max(-currentOffset.y(), delta.height()));
-}
-
-static Node* enclosingLayerNode(RenderLayer*);
-
-bool WebPagePrivate::scrollRenderer(RenderObject* renderer, const IntSize& delta)
-{
-    RenderLayer* layer = renderer->enclosingLayer();
-    if (!layer)
-        return false;
-
-    // Try to scroll layer.
-    bool restrictedByLineClamp = false;
-    if (renderer->parent())
-        restrictedByLineClamp = !renderer->parent()->style()->lineClamp().isNone();
-
-    if (renderer->hasOverflowClip() && !restrictedByLineClamp) {
-        IntSize layerDelta = delta;
-        IntPoint maxOffset(layer->scrollWidth() - layer->renderBox()->clientWidth(), layer->scrollHeight() - layer->renderBox()->clientHeight());
-        IntPoint currentOffset(layer->scrollXOffset(), layer->scrollYOffset());
-        adjustScrollDelta(maxOffset, currentOffset, layerDelta);
-        if (!layerDelta.isZero()) {
-            m_inRegionScrollStartingNode = enclosingLayerNode(layer);
-            IntPoint newOffset = currentOffset + layerDelta;
-            layer->scrollToOffset(toSize(newOffset));
-            renderer->repaint(true);
-            return true;
-        }
-    }
-
-    while (layer = layer->parent()) {
-        if (canScrollRenderBox(layer->renderBox()))
-            return scrollRenderer(layer->renderBox(), delta);
-    }
-
-    return false;
-}
-
 static void handleScrolling(unsigned short character, WebPagePrivate* scroller)
 {
     const int scrollFactor = 20;
@@ -4775,169 +4651,6 @@
     d->m_selectionHandler->selectAtPoint(selectionLocation);
 }
 
-// FIXME: Move to DOMSupport.
-bool WebPagePrivate::canScrollInnerFrame(Frame* frame) const
-{
-    if (!frame || !frame->view())
-        return false;
-
-    // Not having an owner element means that we are on the mainframe.
-    if (!frame->ownerElement())
-        return false;
-
-    ASSERT(frame != m_mainFrame);
-
-    IntSize visibleSize = frame->view()->visibleContentRect().size();
-    IntSize contentsSize = frame->view()->contentsSize();
-
-    bool canBeScrolled = contentsSize.height() > visibleSize.height() || contentsSize.width() > visibleSize.width();
-
-    // Lets also consider the 'overflow-{x,y} property set directly to the {i}frame tag.
-    return canBeScrolled && (frame->ownerElement()->scrollingMode() != ScrollbarAlwaysOff);
-}
-
-// The RenderBox::canbeScrolledAndHasScrollableArea method returns true for the
-// following scenario, for example:
-// (1) a div that has a vertical overflow but no horizontal overflow
-//     with overflow-y: hidden and overflow-x: auto set.
-// The version below fixes it.
-// FIXME: Fix RenderBox::canBeScrolledAndHasScrollableArea method instead.
-bool WebPagePrivate::canScrollRenderBox(RenderBox* box)
-{
-    if (!box || !box->hasOverflowClip())
-        return false;
-
-    if (box->scrollsOverflowX() && (box->scrollWidth() != box->clientWidth())
-        || box->scrollsOverflowY() && (box->scrollHeight() != box->clientHeight()))
-        return true;
-
-    Node* node = box->node();
-    return node && (node->rendererIsEditable() || node->isDocumentNode());
-}
-
-static RenderLayer* parentLayer(RenderLayer* layer)
-{
-    ASSERT(layer);
-    if (layer->parent())
-        return layer->parent();
-
-    RenderObject* renderer = layer->renderer();
-    if (renderer->document() && renderer->document()->ownerElement() && renderer->document()->ownerElement()->renderer())
-        return renderer->document()->ownerElement()->renderer()->enclosingLayer();
-
-    return 0;
-}
-
-// FIXME: Make RenderLayer::enclosingElement public so this one can be removed.
-static Node* enclosingLayerNode(RenderLayer* layer)
-{
-    for (RenderObject* r = layer->renderer(); r; r = r->parent()) {
-        if (Node* e = r->node())
-            return e;
-    }
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-static void pushBackInRegionScrollable(std::vector<Platform::ScrollViewBase*>& vector, InRegionScrollableArea* scroller, WebPagePrivate* webPage)
-{
-    ASSERT(webPage);
-    ASSERT(!scroller.isNull());
-
-    scroller->setCanPropagateScrollingToEnclosingScrollable(!isNonRenderViewFixedPositionedContainer(scroller->layer()));
-    vector.push_back(scroller);
-    if (vector.size() == 1) {
-        // FIXME: Use RenderLayer::renderBox()->node() instead?
-        webPage->m_inRegionScrollStartingNode = enclosingLayerNode(scroller->layer());
-    }
-}
-
-std::vector<Platform::ScrollViewBase*> WebPagePrivate::inRegionScrollableAreasForPoint(const Platform::IntPoint& point)
-{
-    std::vector<Platform::ScrollViewBase*> validReturn;
-    std::vector<Platform::ScrollViewBase*> emptyReturn;
-
-    HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(mapFromViewportToContents(point), false /*allowShadowContent*/);
-    Node* node = result.innerNonSharedNode();
-    if (!node)
-        return emptyReturn;
-
-    RenderObject* renderer = node->renderer();
-    // FIXME: Validate with elements with visibility:hidden.
-    if (!renderer)
-        return emptyReturn;
-
-    RenderLayer* layer = renderer->enclosingLayer();
-    do {
-        RenderObject* renderer = layer->renderer();
-
-        if (renderer->isRenderView()) {
-            if (RenderView* renderView = toRenderView(renderer)) {
-                FrameView* view = renderView->frameView();
-                if (!view)
-                    return emptyReturn;
-
-                if (canScrollInnerFrame(view->frame())) {
-                    pushBackInRegionScrollable(validReturn, new InRegionScrollableArea(this, layer), this);
-                    continue;
-                }
-            }
-        } else if (canScrollRenderBox(layer->renderBox())) {
-            pushBackInRegionScrollable(validReturn, new InRegionScrollableArea(this, layer), this);
-            continue;
-        }
-
-        // If we run into a fix positioned layer, set the last scrollable in-region object
-        // as not able to propagate scroll to its parent scrollable.
-        if (isNonRenderViewFixedPositionedContainer(layer) && validReturn.size()) {
-            Platform::ScrollViewBase* end = validReturn.back();
-            end->setCanPropagateScrollingToEnclosingScrollable(false);
-        }
-
-    } while (layer = parentLayer(layer));
-
-    if (validReturn.empty())
-        return emptyReturn;
-
-    // Post-calculate the visible window rects in reverse hit test order so
-    // we account for all and any clipping rects.
-    WebCore::IntRect recursiveClippingRect(WebCore::IntPoint::zero(), transformedViewportSize());
-
-    std::vector<Platform::ScrollViewBase*>::reverse_iterator rend = validReturn.rend();
-    for (std::vector<Platform::ScrollViewBase*>::reverse_iterator rit = validReturn.rbegin(); rit != rend; ++rit) {
-
-        InRegionScrollableArea* curr = static_cast<InRegionScrollableArea*>(*rit);
-        RenderLayer* layer = curr->layer();
-
-        if (layer && layer->renderer()->isRenderView()) { // #document case
-            FrameView* view = toRenderView(layer->renderer())->frameView();
-            ASSERT(view);
-            ASSERT(canScrollInnerFrame(view->frame()));
-
-            WebCore::IntRect frameWindowRect = mapToTransformed(getRecursiveVisibleWindowRect(view));
-            frameWindowRect.intersect(recursiveClippingRect);
-            curr->setVisibleWindowRect(frameWindowRect);
-            recursiveClippingRect = frameWindowRect;
-
-        } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)).
-
-            RenderBox* box = layer->renderBox();
-            ASSERT(box);
-            ASSERT(canScrollRenderBox(box));
-
-            WebCore::IntRect visibleWindowRect = box->absoluteClippedOverflowRect();
-            visibleWindowRect = box->frame()->view()->contentsToWindow(visibleWindowRect);
-            visibleWindowRect = mapToTransformed(visibleWindowRect);
-            visibleWindowRect.intersect(recursiveClippingRect);
-
-            curr->setVisibleWindowRect(visibleWindowRect);
-            recursiveClippingRect = visibleWindowRect;
-        }
-    }
-
-    return validReturn;
-}
-
 BackingStore* WebPage::backingStore() const
 {
     return d->m_backingStore;

Modified: trunk/Source/WebKit/blackberry/Api/WebPage_p.h (124469 => 124470)


--- trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-08-02 16:42:13 UTC (rev 124470)
@@ -20,6 +20,7 @@
 #define WebPage_p_h
 
 #include "ChromeClient.h"
+#include "InRegionScroller.h"
 #include "InspectorClientBlackBerry.h"
 #include "InspectorOverlay.h"
 #if USE(ACCELERATED_COMPOSITING)
@@ -143,7 +144,6 @@
     bool scrollBy(int deltaX, int deltaY, bool scrollMainFrame = true);
 
     void enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(WebCore::Node*);
-    std::vector<Platform::ScrollViewBase*> inRegionScrollableAreasForPoint(const Platform::IntPoint&);
     void notifyInRegionScrollStatusChanged(bool status);
     void setScrollOriginPoint(const Platform::IntPoint&);
     void setHasInRegionScrollableAreas(bool);
@@ -330,13 +330,6 @@
     WebCore::Frame* focusedOrMainFrame() const;
     WebCore::Frame* mainFrame() const { return m_mainFrame; }
 
-    bool scrollNodeRecursively(WebCore::Node* originalNode, const WebCore::IntSize& delta);
-    bool scrollRenderer(WebCore::RenderObject* renderer, const WebCore::IntSize& delta);
-    void adjustScrollDelta(const WebCore::IntPoint& maxOffset, const WebCore::IntPoint& currentOffset, WebCore::IntSize& delta) const;
-
-    bool canScrollRenderBox(WebCore::RenderBox*);
-    bool canScrollInnerFrame(WebCore::Frame*) const;
-
 #if ENABLE(EVENT_MODE_METATAGS)
     void didReceiveCursorEventMode(WebCore::CursorEventMode);
     void didReceiveTouchEventMode(WebCore::TouchEventMode);
@@ -556,7 +549,7 @@
 
     HashSet<WebCore::PluginView*> m_pluginViews;
 
-    RefPtr<WebCore::Node> m_inRegionScrollStartingNode;
+    OwnPtr<InRegionScroller> m_inRegionScroller;
 
 #if USE(ACCELERATED_COMPOSITING)
     bool m_isAcceleratedCompositingActive;

Modified: trunk/Source/WebKit/blackberry/ChangeLog (124469 => 124470)


--- trunk/Source/WebKit/blackberry/ChangeLog	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/blackberry/ChangeLog	2012-08-02 16:42:13 UTC (rev 124470)
@@ -1,3 +1,57 @@
+2012-08-01  Antonio Gomes  <[email protected]>
+
+        [BlackBerry] Implement InRegionScroller class as a in-region scroll controller
+        https://bugs.webkit.org/show_bug.cgi?id=92889
+        PR #186587
+
+        Reviewed by Yong Li.
+
+        Internally reviewed by Arvid Nilsson.
+
+        Moved all in-region scrolling code out of WebPagePrivate to the just
+        created InRegionScroller class. This class aims to:
+
+        1) Centralize all in-region scroll code and clean up WebPagePrivate as a consequence.
+        2) Be the bases to add UI/Compositing thread driven scrolls to in-region.
+
+        The patch does not change any functionallity change.
+
+        * Api/WebPage.cpp:
+        (BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
+        (BlackBerry::WebKit::WebPagePrivate::init):
+        (BlackBerry::WebKit::WebPagePrivate::scrollBy):
+        (BlackBerry::WebKit::WebPagePrivate::notifyInRegionScrollStatusChanged):
+        (BlackBerry::WebKit::WebPagePrivate::clearDocumentData):
+        (BlackBerry::WebKit::WebPagePrivate::setScrollOriginPoint):
+        * Api/WebPage_p.h:
+        (WebPagePrivate):
+        * WebKitSupport/InRegionScrollableArea.cpp:
+        (BlackBerry::WebKit::InRegionScrollableArea::layer):
+        * WebKitSupport/InRegionScroller.cpp: Added.
+        (WebKit):
+        (BlackBerry::WebKit::canScrollInnerFrame):
+        (BlackBerry::WebKit::canScrollRenderBox):
+        (BlackBerry::WebKit::parentLayer):
+        (BlackBerry::WebKit::enclosingLayerNode):
+        (BlackBerry::WebKit::isNonRenderViewFixedPositionedContainer):
+        (BlackBerry::WebKit::pushBackInRegionScrollable):
+        (BlackBerry::WebKit::InRegionScroller::InRegionScroller):
+        (BlackBerry::WebKit::InRegionScroller::setNode):
+        (BlackBerry::WebKit::InRegionScroller::node):
+        (BlackBerry::WebKit::InRegionScroller::reset):
+        (BlackBerry::WebKit::InRegionScroller::isNull):
+        (BlackBerry::WebKit::InRegionScroller::scrollBy):
+        (BlackBerry::WebKit::InRegionScroller::inRegionScrollableAreasForPoint):
+        (BlackBerry::WebKit::InRegionScroller::scrollNodeRecursively):
+        (BlackBerry::WebKit::InRegionScroller::scrollRenderer):
+        (BlackBerry::WebKit::InRegionScroller::adjustScrollDelta):
+        * WebKitSupport/InRegionScroller.h: Added.
+        (WebCore):
+        (WebKit):
+        (InRegionScroller):
+        * WebKitSupport/TouchEventHandler.cpp:
+        (BlackBerry::WebKit::TouchEventHandler::drawTapHighlight):
+
 2012-08-01  Charles Wei  <[email protected]>
 
         [BlackBerry] Favicon should be Base64 encoded for cross-process passing

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp (124469 => 124470)


--- trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp	2012-08-02 16:42:13 UTC (rev 124470)
@@ -20,7 +20,6 @@
 #include "InRegionScrollableArea.h"
 
 #include "Frame.h"
-#include "NotImplemented.h"
 #include "RenderBox.h"
 #include "RenderLayer.h"
 #include "RenderObject.h"
@@ -104,6 +103,6 @@
     ASSERT(!m_isNull);
     return m_layer;
 }
-}
 
 }
+}

Added: trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.cpp (0 => 124470)


--- trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.cpp	                        (rev 0)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.cpp	2012-08-02 16:42:13 UTC (rev 124470)
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "InRegionScroller.h"
+
+#include "BackingStoreClient.h"
+#include "Frame.h"
+#include "HTMLFrameOwnerElement.h"
+#include "HitTestResult.h"
+#include "InRegionScrollableArea.h"
+#include "RenderBox.h"
+#include "RenderLayer.h"
+#include "RenderObject.h"
+#include "RenderView.h"
+#include "WebPage_p.h"
+
+using namespace WebCore;
+
+namespace BlackBerry {
+namespace WebKit {
+
+static bool canScrollInnerFrame(Frame* frame)
+{
+    if (!frame || !frame->view())
+        return false;
+
+    // Not having an owner element means that we are on the mainframe.
+    if (!frame->ownerElement())
+        return false;
+
+    ASSERT(frame != frame->page()->mainFrame());
+
+    IntSize visibleSize = frame->view()->visibleContentRect().size();
+    IntSize contentsSize = frame->view()->contentsSize();
+
+    bool canBeScrolled = contentsSize.height() > visibleSize.height() || contentsSize.width() > visibleSize.width();
+
+    // Lets also consider the 'overflow-{x,y} property set directly to the {i}frame tag.
+    return canBeScrolled && (frame->ownerElement()->scrollingMode() != ScrollbarAlwaysOff);
+}
+
+// The RenderBox::canbeScrolledAndHasScrollableArea method returns true for the
+// following scenario, for example:
+// (1) a div that has a vertical overflow but no horizontal overflow
+//     with overflow-y: hidden and overflow-x: auto set.
+// The version below fixes it.
+// FIXME: Fix RenderBox::canBeScrolledAndHasScrollableArea method instead.
+static bool canScrollRenderBox(RenderBox* box)
+{
+    if (!box || !box->hasOverflowClip())
+        return false;
+
+    if (box->scrollsOverflowX() && (box->scrollWidth() != box->clientWidth())
+        || box->scrollsOverflowY() && (box->scrollHeight() != box->clientHeight()))
+        return true;
+
+    Node* node = box->node();
+    return node && (node->rendererIsEditable() || node->isDocumentNode());
+}
+
+static RenderLayer* parentLayer(RenderLayer* layer)
+{
+    ASSERT(layer);
+    if (layer->parent())
+        return layer->parent();
+
+    RenderObject* renderer = layer->renderer();
+    if (renderer->document() && renderer->document()->ownerElement() && renderer->document()->ownerElement()->renderer())
+        return renderer->document()->ownerElement()->renderer()->enclosingLayer();
+
+    return 0;
+}
+
+// FIXME: Make RenderLayer::enclosingElement public so this one can be removed.
+static Node* enclosingLayerNode(RenderLayer* layer)
+{
+    for (RenderObject* r = layer->renderer(); r; r = r->parent()) {
+        if (Node* e = r->node())
+            return e;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+static bool isNonRenderViewFixedPositionedContainer(RenderLayer* layer)
+{
+    RenderObject* o = layer->renderer();
+    if (o->isRenderView())
+        return false;
+
+    return o->isPositioned() && o->style()->position() == FixedPosition;
+}
+
+static void pushBackInRegionScrollable(std::vector<Platform::ScrollViewBase*>& vector, InRegionScrollableArea* scrollableArea, InRegionScroller* scroller)
+{
+    ASSERT(webPage);
+    ASSERT(!scrollableArea->isNull());
+
+    scrollableArea->setCanPropagateScrollingToEnclosingScrollable(!isNonRenderViewFixedPositionedContainer(scrollableArea->layer()));
+    vector.push_back(scrollableArea);
+    if (vector.size() == 1) {
+        // FIXME: Use RenderLayer::renderBox()->node() instead?
+        scroller->setNode(enclosingLayerNode(scrollableArea->layer()));
+    }
+}
+
+InRegionScroller::InRegionScroller(WebPagePrivate* webPagePrivate)
+    : m_webPage(webPagePrivate)
+{
+}
+
+void InRegionScroller::setNode(WebCore::Node* node)
+{
+    m_inRegionScrollStartingNode = node;
+}
+
+WebCore::Node* InRegionScroller::node() const
+{
+    return m_inRegionScrollStartingNode.get();
+}
+
+void InRegionScroller::reset()
+{
+    setNode(0);
+}
+
+bool InRegionScroller::hasNode() const
+{
+    return !!m_inRegionScrollStartingNode;
+}
+
+bool InRegionScroller::canScroll() const
+{
+    return hasNode();
+}
+
+bool InRegionScroller::scrollBy(const Platform::IntSize& delta)
+{
+    if (!canScroll())
+        return false;
+
+    return scrollNodeRecursively(node(), delta);
+}
+
+std::vector<Platform::ScrollViewBase*> InRegionScroller::inRegionScrollableAreasForPoint(const WebCore::IntPoint& point)
+{
+    std::vector<Platform::ScrollViewBase*> validReturn;
+    std::vector<Platform::ScrollViewBase*> emptyReturn;
+
+    HitTestResult result = m_webPage->m_mainFrame->eventHandler()->hitTestResultAtPoint(m_webPage->mapFromViewportToContents(point), false /*allowShadowContent*/);
+    Node* node = result.innerNonSharedNode();
+    if (!node || !node->renderer())
+        return emptyReturn;
+
+    RenderLayer* layer = node->renderer()->enclosingLayer();
+    do {
+        RenderObject* renderer = layer->renderer();
+
+        if (renderer->isRenderView()) {
+            if (RenderView* renderView = toRenderView(renderer)) {
+                FrameView* view = renderView->frameView();
+                if (!view)
+                    return emptyReturn;
+
+                if (canScrollInnerFrame(view->frame())) {
+                    pushBackInRegionScrollable(validReturn, new InRegionScrollableArea(m_webPage, layer), this);
+                    continue;
+                }
+            }
+        } else if (canScrollRenderBox(layer->renderBox())) {
+            pushBackInRegionScrollable(validReturn, new InRegionScrollableArea(m_webPage, layer), this);
+            continue;
+        }
+
+        // If we run into a fix positioned layer, set the last scrollable in-region object
+        // as not able to propagate scroll to its parent scrollable.
+        if (isNonRenderViewFixedPositionedContainer(layer) && validReturn.size()) {
+            Platform::ScrollViewBase* end = validReturn.back();
+            end->setCanPropagateScrollingToEnclosingScrollable(false);
+        }
+
+    } while (layer = parentLayer(layer));
+
+    if (validReturn.empty())
+        return emptyReturn;
+
+    // Post-calculate the visible window rects in reverse hit test order so
+    // we account for all and any clipping rects.
+    WebCore::IntRect recursiveClippingRect(WebCore::IntPoint::zero(), m_webPage->transformedViewportSize());
+
+    std::vector<Platform::ScrollViewBase*>::reverse_iterator rend = validReturn.rend();
+    for (std::vector<Platform::ScrollViewBase*>::reverse_iterator rit = validReturn.rbegin(); rit != rend; ++rit) {
+
+        InRegionScrollableArea* curr = static_cast<InRegionScrollableArea*>(*rit);
+        RenderLayer* layer = curr->layer();
+
+        if (layer && layer->renderer()->isRenderView()) { // #document case
+            FrameView* view = toRenderView(layer->renderer())->frameView();
+            ASSERT(view);
+            ASSERT(canScrollInnerFrame(view->frame()));
+
+            WebCore::IntRect frameWindowRect = m_webPage->mapToTransformed(m_webPage->getRecursiveVisibleWindowRect(view));
+            frameWindowRect.intersect(recursiveClippingRect);
+            curr->setVisibleWindowRect(frameWindowRect);
+            recursiveClippingRect = frameWindowRect;
+
+        } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)).
+
+            RenderBox* box = layer->renderBox();
+            ASSERT(box);
+            ASSERT(canScrollRenderBox(box));
+
+            WebCore::IntRect visibleWindowRect = enclosingIntRect(box->absoluteClippedOverflowRect());
+            visibleWindowRect = box->frame()->view()->contentsToWindow(visibleWindowRect);
+            visibleWindowRect = m_webPage->mapToTransformed(visibleWindowRect);
+            visibleWindowRect.intersect(recursiveClippingRect);
+
+            curr->setVisibleWindowRect(visibleWindowRect);
+            recursiveClippingRect = visibleWindowRect;
+        }
+    }
+
+    return validReturn;
+}
+
+bool InRegionScroller::scrollNodeRecursively(WebCore::Node* node, const WebCore::IntSize& delta)
+{
+    if (delta.isZero())
+        return true;
+
+    if (!node)
+        return false;
+
+    RenderObject* renderer = node->renderer();
+    if (!renderer)
+        return false;
+
+    FrameView* view = renderer->view()->frameView();
+    if (!view)
+        return false;
+
+    // Try scrolling the renderer.
+    if (scrollRenderer(renderer, delta))
+        return true;
+
+    // We've hit the page, don't scroll it and return false.
+    if (view == m_webPage->m_mainFrame->view())
+        return false;
+
+    // Try scrolling the FrameView.
+    if (canScrollInnerFrame(view->frame())) {
+        IntSize viewDelta = delta;
+        IntPoint newViewOffset = view->scrollPosition();
+        IntPoint maxViewOffset = view->maximumScrollPosition();
+        adjustScrollDelta(maxViewOffset, newViewOffset, viewDelta);
+
+        if (!viewDelta.isZero()) {
+            view->setCanBlitOnScroll(false);
+
+            BackingStoreClient* backingStoreClient = m_webPage->backingStoreClientForFrame(view->frame());
+            if (backingStoreClient) {
+                backingStoreClient->setIsClientGeneratedScroll(true);
+                backingStoreClient->setIsScrollNotificationSuppressed(true);
+            }
+
+            setNode(view->frame()->document());
+
+            view->scrollBy(viewDelta);
+
+            if (backingStoreClient) {
+                backingStoreClient->setIsClientGeneratedScroll(false);
+                backingStoreClient->setIsScrollNotificationSuppressed(false);
+            }
+
+            return true;
+        }
+    }
+
+    // Try scrolling the node of the enclosing frame.
+    Frame* frame = node->document()->frame();
+    if (frame) {
+        Node* ownerNode = frame->ownerElement();
+        if (scrollNodeRecursively(ownerNode, delta))
+            return true;
+    }
+
+    return false;
+}
+
+bool InRegionScroller::scrollRenderer(WebCore::RenderObject* renderer, const WebCore::IntSize& delta)
+{
+    RenderLayer* layer = renderer->enclosingLayer();
+    if (!layer)
+        return false;
+
+    // Try to scroll layer.
+    bool restrictedByLineClamp = false;
+    if (renderer->parent())
+        restrictedByLineClamp = !renderer->parent()->style()->lineClamp().isNone();
+
+    if (renderer->hasOverflowClip() && !restrictedByLineClamp) {
+        IntSize layerDelta = delta;
+        IntPoint maxOffset(layer->scrollWidth() - layer->renderBox()->clientWidth(), layer->scrollHeight() - layer->renderBox()->clientHeight());
+        IntPoint currentOffset(layer->scrollXOffset(), layer->scrollYOffset());
+        adjustScrollDelta(maxOffset, currentOffset, layerDelta);
+        if (!layerDelta.isZero()) {
+            setNode(enclosingLayerNode(layer));
+            IntPoint newOffset = currentOffset + layerDelta;
+            layer->scrollToOffset(newOffset.x(), newOffset.y());
+            renderer->repaint(true);
+            return true;
+        }
+    }
+
+    while (layer = layer->parent()) {
+        if (canScrollRenderBox(layer->renderBox()))
+            return scrollRenderer(layer->renderBox(), delta);
+    }
+
+    return false;
+}
+
+void InRegionScroller::adjustScrollDelta(const WebCore::IntPoint& maxOffset, const WebCore::IntPoint& currentOffset, WebCore::IntSize& delta) const
+{
+    if (currentOffset.x() + delta.width() > maxOffset.x())
+        delta.setWidth(std::min(maxOffset.x() - currentOffset.x(), delta.width()));
+
+    if (currentOffset.x() + delta.width() < 0)
+        delta.setWidth(std::max(-currentOffset.x(), delta.width()));
+
+    if (currentOffset.y() + delta.height() > maxOffset.y())
+        delta.setHeight(std::min(maxOffset.y() - currentOffset.y(), delta.height()));
+
+    if (currentOffset.y() + delta.height() < 0)
+        delta.setHeight(std::max(-currentOffset.y(), delta.height()));
+}
+
+}
+}

Added: trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.h (0 => 124470)


--- trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.h	                        (rev 0)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/InRegionScroller.h	2012-08-02 16:42:13 UTC (rev 124470)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef InRegionScroller_h
+#define InRegionScroller_h
+
+#include "IntRect.h"
+
+#include <interaction/ScrollViewBase.h>
+#include <vector>
+
+namespace WebCore {
+class Frame;
+class Node;
+class RenderObject;
+}
+
+namespace BlackBerry {
+namespace WebKit {
+
+class WebPagePrivate;
+
+class InRegionScroller {
+
+public:
+    InRegionScroller(WebPagePrivate*);
+
+    void setNode(WebCore::Node*);
+    WebCore::Node* node() const;
+    void reset();
+
+    bool canScroll() const;
+    bool hasNode() const;
+
+    bool scrollBy(const Platform::IntSize& delta);
+
+    std::vector<Platform::ScrollViewBase*> inRegionScrollableAreasForPoint(const WebCore::IntPoint&);
+private:
+
+    bool scrollNodeRecursively(WebCore::Node*, const WebCore::IntSize& delta);
+    bool scrollRenderer(WebCore::RenderObject*, const WebCore::IntSize& delta);
+
+    void adjustScrollDelta(const WebCore::IntPoint& maxOffset, const WebCore::IntPoint& currentOffset, WebCore::IntSize& delta) const;
+
+    RefPtr<WebCore::Node> m_inRegionScrollStartingNode;
+    WebPagePrivate* m_webPage;
+};
+
+}
+}
+
+#endif

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp (124469 => 124470)


--- trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp	2012-08-02 16:36:56 UTC (rev 124469)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp	2012-08-02 16:42:13 UTC (rev 124470)
@@ -363,7 +363,7 @@
     // On the client side, this info is being used to hide the tap highlight window on scroll.
     RenderLayer* layer = m_webPage->enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(renderer->enclosingLayer());
     bool shouldHideTapHighlightRightAfterScrolling = !layer->renderer()->isRenderView();
-    shouldHideTapHighlightRightAfterScrolling |= !!m_webPage->m_inRegionScrollStartingNode.get();
+    shouldHideTapHighlightRightAfterScrolling |= !!m_webPage->m_inRegionScroller->node();
 
     IntPoint framePos(m_webPage->frameOffset(elementFrame));
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to