summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Scott <phanna@android.com>2010-08-02 08:09:31 -0400
committerPatrick Scott <phanna@android.com>2010-08-02 15:28:47 -0400
commitef1adcdfc805d4d13103f6f15cc5b4d96828a60f (patch)
treecf24fb4142aa8bd487b7f751c74aa4225967fa47
parent2e79b71868fcdcd0de7c6070e50662d8fa01e4ab (diff)
downloadexternal_webkit-ef1adcdfc805d4d13103f6f15cc5b4d96828a60f.zip
external_webkit-ef1adcdfc805d4d13103f6f15cc5b4d96828a60f.tar.gz
external_webkit-ef1adcdfc805d4d13103f6f15cc5b4d96828a60f.tar.bz2
Enable navigation in scrollable layers.
EventHandler: * Added IgnoreClipping in order to touch nodes that are clipped out. android_graphics: * Remember the absolute bounds of the node for invals. RenderBox: * Fix a compiler warning. RenderLayer: * Do not record the entire layer contents unless the scroll dimensions are larger than the client dimensions. * Change isSelfPaintingLayer to check for an overflow clip instead of the scrollable dimensions since it can be too early to check at this point. RenderLayerCompositor: * Same as RenderLayer for checking the overflow clip. WebViewCore: * Scroll the containing layer to the node bounds and offset the mouse position if scrolled. Once the mouse event is processed, restore the layer to 0,0. CacheBuilder: * The body position is no longer used. * Do not clip out nodes if the layer is scrollable. CachedFrame: * Add unadjustBounds to restore adjusted bounds to their original position (fixed position elements). * Call unadjustBounds when a node has been found. This new set of bounds is passed over to WebViewCore to handle clicks. * Reject empty node bounds. CachedLayer: * Document adjustBounds and add unadjustBounds. Add in the scroll position to the node bounds. CachedRoot: * Unadjust the mouse bounds. WebView: * Unadjust the mouse bounds and use the absolute bounds of the ring during inval. Bug: 1566791 Change-Id: Ia55f2cbb61869087176d3ff61882e40324614c6a
-rw-r--r--WebCore/page/EventHandler.cpp14
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h4
-rw-r--r--WebCore/platform/graphics/android/android_graphics.cpp2
-rw-r--r--WebCore/platform/graphics/android/android_graphics.h1
-rw-r--r--WebCore/rendering/RenderBox.cpp8
-rw-r--r--WebCore/rendering/RenderLayer.cpp26
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp15
-rw-r--r--WebKit/android/jni/WebViewCore.cpp58
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp17
-rw-r--r--WebKit/android/nav/CachedFrame.cpp32
-rw-r--r--WebKit/android/nav/CachedFrame.h2
-rw-r--r--WebKit/android/nav/CachedLayer.cpp75
-rw-r--r--WebKit/android/nav/CachedLayer.h7
-rw-r--r--WebKit/android/nav/CachedRoot.cpp4
-rw-r--r--WebKit/android/nav/WebView.cpp9
15 files changed, 212 insertions, 62 deletions
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index 89e9424..e2fab6e 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -1257,7 +1257,14 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
}
m_mouseDownWasInSubframe = false;
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // Add IgnoreClipping because fixed position elements are moved only on the
+ // UI thread. Nodes in fixed position elements are clipped out by the view
+ // without IgnoreClipping.
+ HitTestRequest request(HitTestRequest::Active | HitTestRequest::IgnoreClipping);
+#else
HitTestRequest request(HitTestRequest::Active);
+#endif
// Save the document point we generate in case the window coordinate is invalidated by what happens
// when we dispatch the event.
IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.pos());
@@ -1575,7 +1582,14 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
return m_lastScrollbarUnderMouse->mouseUp();
}
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // Add IgnoreClipping because fixed position elements are moved only on the
+ // UI thread. Nodes in fixed position elements are clipped out by the view
+ // without IgnoreClipping.
+ HitTestRequest request(HitTestRequest::MouseUp | HitTestRequest::IgnoreClipping);
+#else
HitTestRequest request(HitTestRequest::MouseUp);
+#endif
MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
if (m_eventHandlerWillResetCapturingMouseEventsNode)
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
index b74a8c8..712d699 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -135,6 +135,10 @@ public:
void setForegroundClip(const SkRect& clip) {
m_foregroundClip = clip;
}
+
+ // Return the foreground clip offset by the position of the layer.
+ SkRect foregroundClip() const { return m_foregroundClip; }
+
bool contentIsScrollable() const;
// Returns true if the content position has changed.
diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp
index fafd3df..a5dafda 100644
--- a/WebCore/platform/graphics/android/android_graphics.cpp
+++ b/WebCore/platform/graphics/android/android_graphics.cpp
@@ -140,7 +140,9 @@ bool CursorRing::setup()
m_rings.clear();
m_rings.append(m_bounds);
}
+ m_absBounds = m_node->bounds(m_frame);
m_bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER));
+ m_absBounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER));
if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus()))
return false;
m_flavor = NORMAL_FLAVOR;
diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h
index dbf1978..46c60e8 100644
--- a/WebCore/platform/graphics/android/android_graphics.h
+++ b/WebCore/platform/graphics/android/android_graphics.h
@@ -71,6 +71,7 @@ private:
WebViewCore* m_viewImpl; // copy for convenience
WTF::Vector<IntRect> m_rings;
IntRect m_bounds;
+ IntRect m_absBounds;
const CachedRoot* m_root;
const CachedFrame* m_frame;
const CachedNode* m_node;
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index 8d18440..2deeffc 100644
--- a/WebCore/rendering/RenderBox.cpp
+++ b/WebCore/rendering/RenderBox.cpp
@@ -73,10 +73,6 @@ bool RenderBox::s_hadOverflowClip = false;
RenderBox::RenderBox(Node* node)
: RenderBoxModelObject(node)
-#ifdef ANDROID_LAYOUT
- , m_visibleWidth(0)
- , m_isVisibleWidthChangedBeforeLayout(false)
-#endif
, m_marginLeft(0)
, m_marginRight(0)
, m_marginTop(0)
@@ -84,6 +80,10 @@ RenderBox::RenderBox(Node* node)
, m_minPrefWidth(-1)
, m_maxPrefWidth(-1)
, m_inlineBoxWrapper(0)
+#ifdef ANDROID_LAYOUT
+ , m_visibleWidth(0)
+ , m_isVisibleWidthChangedBeforeLayout(false)
+#endif
{
setIsBox();
}
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index f0c6333..368a1a7 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -3238,16 +3238,18 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (renderer()->hasOverflowClip()) {
+ if (renderer()->hasOverflowClip() &&
+ !m_scrollDimensionsDirty &&
+ (m_scrollWidth > renderBox()->clientWidth() ||
+ m_scrollHeight > renderBox()->clientHeight())) {
RenderBox* box = toRenderBox(renderer());
layerBounds = backgroundRect = foregroundRect = outlineRect =
IntRect(x, y, box->borderLeft() + box->borderRight() + m_scrollWidth,
box->borderTop() + box->borderBottom() + m_scrollHeight);
- }
-#else
+ } else
+#endif
if (renderer()->hasOverflowClip())
foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y));
-#endif
if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
@@ -3757,24 +3759,10 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
&& !isTransparent();
}
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-static bool hasOverflowScroll(const RenderLayer* layer)
-{
- RenderBox* box = layer->renderBox();
- if (!box || !box->node() || !box->node()->hasTagName(HTMLNames::divTag))
- return false;
- EOverflow x = box->style()->overflowX();
- EOverflow y = box->style()->overflowY();
- return (x == OAUTO || x == OSCROLL || y == OAUTO || y == OSCROLL) &&
- (box->scrollWidth() > box->clientWidth() ||
- box->scrollHeight() > box->clientHeight());
-}
-#endif
-
bool RenderLayer::isSelfPaintingLayer() const
{
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (hasOverflowScroll(this))
+ if (renderer()->hasOverflowClip())
return true;
#endif
return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo() || renderer()->isEmbeddedObject() || renderer()->isRenderIFrame();
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index 46278a2..f6e1442 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1155,19 +1155,6 @@ bool RenderLayerCompositor::requiresCompositingForMobileSites(const RenderLayer*
}
#endif
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-static bool requiresCompositingForOverflowScroll(const RenderLayer* layer) {
- RenderBox* box = layer->renderBox();
- if (!box || !box->node()->hasTagName(HTMLNames::divTag))
- return false;
- EOverflow x = box->style()->overflowX();
- EOverflow y = box->style()->overflowY();
- return (x == OAUTO || x == OSCROLL || y == OAUTO || y == OSCROLL) &&
- (box->scrollWidth() > box->clientWidth() ||
- box->scrollHeight() > box->clientHeight());
-}
-#endif
-
// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
// static
@@ -1183,7 +1170,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
#if PLATFORM(ANDROID)
|| requiresCompositingForMobileSites(layer)
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- || requiresCompositingForOverflowScroll(layer)
+ || renderer->hasOverflowClip()
#endif
#endif
|| requiresCompositingForVideo(renderer)
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 3da678e..9d2a430 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -2357,6 +2357,59 @@ void WebViewCore::touchUp(int touchGeneration,
handleMouseClick(frame, node);
}
+// Return the RenderLayer for the given RenderObject only if the layer is
+// composited and it contains a scrollable content layer.
+static WebCore::RenderLayer* getLayerFromRenderer(WebCore::RenderObject* renderer)
+{
+ if (!renderer)
+ return 0;
+ WebCore::RenderLayer* layer = renderer->enclosingSelfPaintingLayer();
+ if (!layer || !layer->backing())
+ return 0;
+ GraphicsLayerAndroid* graphicsLayer =
+ static_cast<GraphicsLayerAndroid*>(layer->backing()->graphicsLayer());
+ if (!graphicsLayer)
+ return 0;
+ LayerAndroid* aLayer = graphicsLayer->contentLayer();
+ if (!aLayer || !aLayer->contentIsScrollable())
+ return 0;
+ return layer;
+}
+
+// Scroll the RenderLayer associated with a scrollable div element. This is
+// done so that the node is visible when it is clicked.
+static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos)
+{
+ WebCore::RenderLayer* layer = getLayerFromRenderer(renderer);
+ if (!layer)
+ return;
+ WebCore::IntRect absBounds = renderer->absoluteBoundingBoxRect();
+ WebCore::IntRect layerBounds = layer->absoluteBoundingBox();
+
+ // Move the node's bounds into the layer's coordinates.
+ absBounds.move(-layerBounds.x(), -layerBounds.y());
+
+ // Scroll the layer to the node's position. The false parameters tell the
+ // layer not to invalidate.
+ layer->scrollToOffset(absBounds.x(), absBounds.y(), false, false);
+
+ // Update the mouse position to the layer offset.
+ pos->move(-layer->scrollXOffset(), -layer->scrollYOffset());
+}
+
+static void restoreScrolledLayer(WebCore::RenderObject* renderer,
+ WebCore::IntPoint* pos)
+{
+ WebCore::RenderLayer* layer = getLayerFromRenderer(renderer);
+ if (!layer)
+ return;
+ // Move the mouse position back to it's original position.
+ pos->move(layer->scrollXOffset(), layer->scrollYOffset());
+
+ // Scroll the layer back to 0,0.
+ layer->scrollToOffset(0, 0, false, false);
+}
+
// Common code for both clicking with the trackball and touchUp
bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
{
@@ -2373,6 +2426,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
DBG_NAV_LOG("area");
return true;
}
+
WebCore::RenderObject* renderer = nodePtr->renderer();
if (renderer && (renderer->isMenuList() || renderer->isListBox())) {
WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr);
@@ -2415,6 +2469,8 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
}
if (!valid || !framePtr)
framePtr = m_mainFrame;
+ if (nodePtr && valid)
+ scrollLayer(nodePtr->renderer(), &m_mousePos);
webFrame->setUserInitiatedClick(true);
WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton,
WebCore::MouseEventPressed, 1, false, false, false, false,
@@ -2451,6 +2507,8 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
requestKeyboard(true);
}
}
+ if (nodePtr && valid)
+ restoreScrolledLayer(nodePtr->renderer(), &m_mousePos);
return handled;
}
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 5fddc48..b4a91bc 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -979,7 +979,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
cachedRoot->setFocusBounds(focused->getRect());
int globalOffsetX, globalOffsetY;
GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY);
- IntPoint bodyPos = IntPoint(0, 0);
while (walk.mMore || (node = node->traverseNextNode()) != NULL) {
#if DUMP_NAV_CACHE
nodeIndex++;
@@ -1062,7 +1061,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
#if USE(ACCELERATED_COMPOSITING)
if (nodeRenderer->hasLayer()) {
TrackLayer(layerTracker, nodeRenderer, lastChild,
- globalOffsetX - bodyPos.x(), globalOffsetY - bodyPos.y());
+ globalOffsetX, globalOffsetY);
size_t size = tracker.size();
const LayerAndroid* layer = layerTracker.last().mLayer;
if (layer) {
@@ -1129,10 +1128,15 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
originalAbsBounds = absBounds;
absBounds.move(globalOffsetX, globalOffsetY);
hasClip = nodeRenderer->hasOverflowClip();
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ if (nodeRenderer->hasLayer()) {
+ const LayerAndroid* layer = layerTracker.last().mLayer;
+ if (layer && layer->contentIsScrollable())
+ hasClip = false;
+ }
+#endif
- if (node->hasTagName(HTMLNames::bodyTag))
- bodyPos = originalAbsBounds.location();
- else if (node->hasTagName(HTMLNames::canvasTag))
+ if (node->hasTagName(HTMLNames::canvasTag))
mPictureSetDisabled = true;
if (checkForPluginViewThatWantsFocus(nodeRenderer)) {
bounds = absBounds;
@@ -1323,7 +1327,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
LayerAndroid* layer = layerTracker.last().mLayer;
if (layer) {
const IntRect& layerClip = layerTracker.last().mBounds;
- if (!layerClip.isEmpty() && !cachedNode.clip(layerClip)) {
+ if (!layer->contentIsScrollable() && !layerClip.isEmpty() &&
+ !cachedNode.clip(layerClip)) {
DBG_NAV_LOGD("skipped on layer clip %d", cacheIndex);
continue; // skip this node if outside of the clip
}
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp
index ff13508..3bf16fc 100644
--- a/WebKit/android/nav/CachedFrame.cpp
+++ b/WebKit/android/nav/CachedFrame.cpp
@@ -48,6 +48,19 @@ WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node,
#endif
}
+// This is for nodes inside a layer. It takes an IntRect that has been
+// adjusted by the layer's position and removes the adjustment made by the
+// layer.
+WebCore::IntRect CachedFrame::unadjustBounds(const CachedNode* node,
+ const WebCore::IntRect& rect) const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (node->isInLayer())
+ return layer(node)->unadjustBounds(mRoot->rootLayer(), rect);
+#endif
+ return rect;
+}
+
bool CachedFrame::CheckBetween(Direction direction, const WebCore::IntRect& bestRect,
const WebCore::IntRect& prior, WebCore::IntRect* result)
{
@@ -394,8 +407,10 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect,
if (*directHit == NULL) {
*directHit = test;
*directHitFramePtr = this;
- *x = center.x();
- *y = center.y();
+ IntRect r(center, IntSize(0, 0));
+ r = unadjustBounds(test, r);
+ *x = r.x();
+ *y = r.y();
} else {
// We have hit another one before
const CachedNode* d = *directHit;
@@ -436,6 +451,7 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect,
*inside = testInside;
result = test;
*framePtr = this;
+ both = unadjustBounds(test, both);
*x = both.x() + (both.width() >> 1);
*y = both.y() + (both.height() >> 1);
}
@@ -500,6 +516,7 @@ const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect,
if (cursorRect.intersects(rect)) {
WebCore::IntRect intersection(cursorRect);
intersection.intersect(rect);
+ intersection = unadjustBounds(test, intersection);
*x = intersection.x() + (intersection.width() >> 1);
*y = intersection.y() + (intersection.height() >> 1);
*framePtr = this;
@@ -696,12 +713,17 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test,
testData.mNode->setCondition(CachedNode::DISABLED);
return REJECT_TEST;
}
- if (mRoot->scrolledBounds().intersects(test->bounds(this)) == false) {
+ WebCore::IntRect bounds = test->bounds(this);
+ if (bounds.isEmpty()) {
+ testData.mNode->setCondition(CachedNode::NAVABLE);
+ return REJECT_TEST;
+ }
+ if (mRoot->scrolledBounds().intersects(bounds) == false) {
testData.mNode->setCondition(CachedNode::NAVABLE);
return REJECT_TEST;
}
if (mRoot->rootLayer() && !test->isInLayer()
- && !mRoot->baseUncovered().intersects(test->bounds(this))) {
+ && !mRoot->baseUncovered().intersects(bounds)) {
testData.mNode->setCondition(CachedNode::UNDER_LAYER);
return REJECT_TEST;
}
@@ -901,7 +923,7 @@ WebCore::IntRect CachedFrame::localBounds(const CachedNode* node,
DBG_NAV_LOGD("node=%p [%d] rect=(%d,%d,w=%d,h=%d)",
node, node->index(), rect.x(), rect.y(), rect.width(), rect.height());
#if USE(ACCELERATED_COMPOSITING)
- return layer(node)->localBounds(rect);
+ return layer(node)->localBounds(mRoot->rootLayer(), rect);
#else
return rect;
#endif
diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h
index 9334707..caba482 100644
--- a/WebKit/android/nav/CachedFrame.h
+++ b/WebKit/android/nav/CachedFrame.h
@@ -78,6 +78,8 @@ public:
void addFrame(CachedFrame& child) { mCachedFrames.append(child); }
WebCore::IntRect adjustBounds(const CachedNode* ,
const WebCore::IntRect& ) const;
+ WebCore::IntRect unadjustBounds(const CachedNode*,
+ const WebCore::IntRect& ) const;
bool checkRings(const CachedNode* node,
const WTF::Vector<WebCore::IntRect>& rings,
const WebCore::IntRect& bounds) const;
diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp
index 2f6e20a..9c7d59b 100644
--- a/WebKit/android/nav/CachedLayer.cpp
+++ b/WebKit/android/nav/CachedLayer.cpp
@@ -46,23 +46,67 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
return bounds;
}
FloatRect temp = bounds;
+ // First, remove the original offset from the bounds.
+ temp.move(-mOffset.x(), -mOffset.y());
+
+ // Next, add in the new position of the layer (could be different due to a
+ // fixed position layer).
const FloatPoint& position = aLayer->getPosition();
temp.move(position.x(), position.y());
+
+ // Add in any layer translation.
const FloatPoint& translation = aLayer->translation();
temp.move(translation.x(), translation.y());
+
+ // Move the bounds by the layer's internal scroll position.
+ const SkPoint& scroll = aLayer->scrollPosition();
+ temp.move(SkScalarToFloat(-scroll.fX), SkScalarToFloat(-scroll.fY));
+
IntRect result = enclosingIntRect(temp);
+
+ // Finally, clip the result to the foreground (this includes the object's
+ // border which does not scroll).
+ IntRect clip(aLayer->foregroundClip());
+ clip.move(position.x(), position.y());
+ result.intersect(clip);
+
DBG_NAV_LOGD("root=%p aLayer=%p [%d]"
- " bounds=(%d,%d,w=%d,h=%d) pos=(%g,%g) trans=(%g,%g)"
- " result=(%d,%d,w=%d,h=%d) offset=(%d,%d)",
+ " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g)"
+ " offset=(%d,%d) clip=(%d,%d,w=%d,h=%d)"
+ " result=(%d,%d,w=%d,h=%d)",
root, aLayer, aLayer->uniqueId(),
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
- position.x(), position.y(), translation.x(), translation.y(),
- result.x(), result.y(), result.width(), result.height(),
- mOffset.x(), mOffset.y());
- result.move(-mOffset.x(), -mOffset.y());
+ translation.x(), translation.y(), mOffset.x(), mOffset.y(),
+ clip.x(), clip.y(), clip.width(), clip.height(),
+ result.x(), result.y(), result.width(), result.height());
return result;
}
+IntRect CachedLayer::unadjustBounds(const LayerAndroid* root,
+ const IntRect& bounds) const
+{
+ const LayerAndroid* aLayer = layer(root);
+ if (!aLayer)
+ return bounds;
+
+ IntRect temp = bounds;
+ // Remove the new position (i.e. fixed position elements).
+ const FloatPoint& position = aLayer->getPosition();
+ temp.move(-position.x(), -position.y());
+
+ // Remove any layer translation.
+ const FloatPoint& translation = aLayer->translation();
+ temp.move(-translation.x(), -translation.y());
+
+ // Move the bounds by the internal scroll position.
+ const SkPoint& scroll = aLayer->scrollPosition();
+ temp.move(SkScalarRound(scroll.fX), SkScalarRound(scroll.fY));
+
+ // Move it back to the original offset.
+ temp.move(mOffset.x(), mOffset.y());
+ return temp;
+}
+
const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
{
if (!root || mLayer)
@@ -71,11 +115,26 @@ const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
}
// return bounds relative to enclosing layer as recorded when walking the dom
-IntRect CachedLayer::localBounds(const IntRect& bounds) const
+IntRect CachedLayer::localBounds(const LayerAndroid* root,
+ const IntRect& bounds) const
{
IntRect temp = bounds;
+ // Remove the original offset from the bounds.
temp.move(-mOffset.x(), -mOffset.y());
- return temp;
+
+ const LayerAndroid* aLayer = layer(root);
+ if (aLayer) {
+ // Move the bounds by the scroll position of the layer.
+ const SkPoint& scroll = aLayer->scrollPosition();
+ temp.move(SkScalarToFloat(-scroll.fX), SkScalarToFloat(-scroll.fY));
+
+ // Clip by the layer's foreground bounds. Since the bounds have
+ // already be moved local to the layer, no need to move the foreground
+ // clip.
+ temp.intersect(IntRect(aLayer->foregroundClip()));
+ }
+
+ return enclosingIntRect(temp);
}
SkPicture* CachedLayer::picture(const LayerAndroid* root) const
diff --git a/WebKit/android/nav/CachedLayer.h b/WebKit/android/nav/CachedLayer.h
index c802407..8bfe922 100644
--- a/WebKit/android/nav/CachedLayer.h
+++ b/WebKit/android/nav/CachedLayer.h
@@ -47,10 +47,13 @@ public:
}
// FIXME: adjustBounds should be renamed globalBounds or toGlobal
IntRect adjustBounds(const LayerAndroid* root, const IntRect& bounds) const;
+ // Moves the bounds by the layer's scroll position. Assumes the incoming
+ // bounds have been adjusted by adjustBounds.
+ IntRect unadjustBounds(const LayerAndroid* root,
+ const IntRect& bounds) const;
int cachedNodeIndex() const { return mCachedNodeIndex; }
- const IntPoint& getOffset() const { return mOffset; }
const LayerAndroid* layer(const LayerAndroid* root) const;
- IntRect localBounds(const IntRect& bounds) const;
+ IntRect localBounds(const LayerAndroid* root, const IntRect& bounds) const;
SkPicture* picture(const LayerAndroid* root) const;
void reset() { mLayer = 0; }
void setCachedNodeIndex(int index) { mCachedNodeIndex = index; }
diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp
index 2d37a2a..6016d28 100644
--- a/WebKit/android/nav/CachedRoot.cpp
+++ b/WebKit/android/nav/CachedRoot.cpp
@@ -999,7 +999,9 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
if (bestData->mNode != NULL) {
mHistory->addToVisited(bestData->mNode, direction);
mHistory->mNavBounds = bestData->bounds();
- mHistory->mMouseBounds = bestData->mouseBounds();
+ mHistory->mMouseBounds =
+ cursorFrame->unadjustBounds(bestData->mNode,
+ bestData->mouseBounds());
} else if (scroll->x() != 0 || scroll->y() != 0) {
WebCore::IntRect newBounds = mHistory->mNavBounds;
int offsetX = scroll->x();
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index aad3501..9108fdb 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -385,7 +385,7 @@ void drawCursorPostamble()
if (time < m_ringAnimationEnd) {
// views assume that inval bounds coordinates are non-negative
WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX);
- invalBounds.intersect(m_ring.m_bounds);
+ invalBounds.intersect(m_ring.m_absBounds);
postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds);
} else {
if (m_ring.m_followedLink)
@@ -829,7 +829,8 @@ void selectBestAt(const WebCore::IntRect& rect)
root->setCursor(0, 0);
} else {
DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
- root->rootHistory()->setMouseBounds(node->bounds(frame));
+ WebCore::IntRect bounds = node->bounds(frame);
+ root->rootHistory()->setMouseBounds(frame->unadjustBounds(node, bounds));
m_viewImpl->updateCursorBounds(root, frame, node);
root->setCursor(const_cast<CachedFrame*>(frame),
const_cast<CachedNode*>(node));
@@ -897,6 +898,8 @@ bool motionUp(int x, int y, int slop)
}
DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
result->index(), x, y, rx, ry);
+ // No need to call unadjustBounds below. rx and ry are already adjusted to
+ // the absolute position of the node.
WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
setNavBounds(navBounds);
root->rootHistory()->setMouseBounds(navBounds);
@@ -1965,7 +1968,7 @@ static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
if (!next)
return false;
const WebCore::IntRect& bounds = next->bounds(frame);
- root->rootHistory()->setMouseBounds(bounds);
+ root->rootHistory()->setMouseBounds(frame->unadjustBounds(next, bounds));
view->getWebViewCore()->updateCursorBounds(root, frame, next);
root->setCursor(const_cast<CachedFrame*>(frame),
const_cast<CachedNode*>(next));