diff options
author | Grace Kloba <klobag@google.com> | 2010-05-18 21:59:53 -0700 |
---|---|---|
committer | Grace Kloba <klobag@google.com> | 2010-05-24 21:41:25 -0700 |
commit | 17dcead8ee9edfa8f75e7e2d2284ed3c6f4bd403 (patch) | |
tree | 8d89d459030792e918c95900963217ec89287eab /WebCore | |
parent | 40a65b8dda8d56276893edcc25c957d13b3a9b77 (diff) | |
download | external_webkit-17dcead8ee9edfa8f75e7e2d2284ed3c6f4bd403.zip external_webkit-17dcead8ee9edfa8f75e7e2d2284ed3c6f4bd403.tar.gz external_webkit-17dcead8ee9edfa8f75e7e2d2284ed3c6f4bd403.tar.bz2 |
First draft to add a fat point to WebKit hit test.
If padding is 0, it is the old style point hit test.
If it finds a node, it will break the search loop
and return.
If padding is non-zero, the first node will be added
to HitTestResult's innerNode as before. But instead
of finishing the search, hit test will continue to
look for other nodes covered by the fat point unless
it is fully inside the current node.
Here are some highlights of the changes.
. instead of testing renderRect.contains(x, y),
we now test renderRect.intersect(pointRect)
. when a Node is hit, it will be appended to the
rawNodeList of HitTestResult. So the order inside
the rawNodeList represents the hit test order.
Currently the fat point doesn't support SVG nodes.
It also doesn't support overflow control yet.
Diffstat (limited to 'WebCore')
-rw-r--r-- | WebCore/config.h | 3 | ||||
-rw-r--r-- | WebCore/page/EventHandler.cpp | 12 | ||||
-rw-r--r-- | WebCore/page/EventHandler.h | 4 | ||||
-rw-r--r-- | WebCore/rendering/EllipsisBox.cpp | 13 | ||||
-rw-r--r-- | WebCore/rendering/HitTestResult.cpp | 63 | ||||
-rw-r--r-- | WebCore/rendering/HitTestResult.h | 22 | ||||
-rw-r--r-- | WebCore/rendering/InlineFlowBox.cpp | 16 | ||||
-rw-r--r-- | WebCore/rendering/InlineTextBox.cpp | 12 | ||||
-rw-r--r-- | WebCore/rendering/RenderBlock.cpp | 36 | ||||
-rw-r--r-- | WebCore/rendering/RenderBox.cpp | 16 | ||||
-rw-r--r-- | WebCore/rendering/RenderImage.cpp | 12 | ||||
-rw-r--r-- | WebCore/rendering/RenderLayer.cpp | 68 | ||||
-rw-r--r-- | WebCore/rendering/RenderLineBoxList.cpp | 11 | ||||
-rw-r--r-- | WebCore/rendering/RenderSVGRoot.cpp | 10 | ||||
-rw-r--r-- | WebCore/rendering/RenderTable.cpp | 20 | ||||
-rw-r--r-- | WebCore/rendering/RenderTableSection.cpp | 7 | ||||
-rw-r--r-- | WebCore/rendering/RenderWidget.cpp | 6 |
17 files changed, 331 insertions, 0 deletions
diff --git a/WebCore/config.h b/WebCore/config.h index c812ee8..8e324a5 100644 --- a/WebCore/config.h +++ b/WebCore/config.h @@ -195,6 +195,9 @@ // Enable prefetching when specified via the rel element of <link> elements. #define ENABLE_LINK_PREFETCH 1 +// Enable hit test with point plus a size +#define ANDROID_HITTEST_WITHSIZE + #endif /* PLATFORM(ANDROID) */ #ifdef __cplusplus diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index 8f63144..042f3d4 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -865,9 +865,17 @@ void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const } #endif // ENABLE(DRAG_SUPPORT) +#ifdef ANDROID_HITTEST_WITHSIZE +HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, const IntSize& pointPadding) +#else HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars) +#endif { +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult result(point, pointPadding); +#else HitTestResult result(point); +#endif if (!m_frame->contentRenderer()) return result; int hitType = HitTestRequest::ReadOnly | HitTestRequest::Active; @@ -889,7 +897,11 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all FrameView* view = static_cast<FrameView*>(widget); IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(), result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop()); +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult widgetHitTestResult(widgetPoint, pointPadding); +#else HitTestResult widgetHitTestResult(widgetPoint); +#endif frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult); result = widgetHitTestResult; diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h index c83925c..39b165d 100644 --- a/WebCore/page/EventHandler.h +++ b/WebCore/page/EventHandler.h @@ -105,7 +105,11 @@ public: void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&); +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false, HitTestScrollbars scrollbars = DontHitTestScrollbars, const IntSize& pointPadding = IntSize()); +#else HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false, HitTestScrollbars scrollbars = DontHitTestScrollbars); +#endif bool mousePressed() const { return m_mousePressed; } void setMousePressed(bool pressed) { m_mousePressed = pressed; } diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp index 6f25861..4a64fe4 100644 --- a/WebCore/rendering/EllipsisBox.cpp +++ b/WebCore/rendering/EllipsisBox.cpp @@ -113,8 +113,21 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } } +#ifdef ANDROID_HITTEST_WITHSIZE + IntRect boundsRect = IntRect(tx, ty, m_width, m_height); + if (visibleToHitTesting() && result.intersects(x, y, boundsRect)) { +#else if (visibleToHitTesting() && IntRect(tx, ty, m_width, m_height).contains(x, y)) { +#endif renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(renderer()->node() || renderer()->isAnonymous()); + result.addRawNode(renderer()->node()); + if (!result.containedBy(x, y, boundsRect)) + return false; + } +#endif return true; } diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index 50933c6..8a4ef3c 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -52,6 +52,15 @@ HitTestResult::HitTestResult(const IntPoint& point) { } +#ifdef ANDROID_HITTEST_WITHSIZE +HitTestResult::HitTestResult(const IntPoint& point, const IntSize& padding) + : m_point(point) + , m_pointPadding(padding) + , m_isOverWidget(false) +{ +} +#endif + HitTestResult::HitTestResult(const HitTestResult& other) : m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) @@ -60,6 +69,10 @@ HitTestResult::HitTestResult(const HitTestResult& other) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) +#ifdef ANDROID_HITTEST_WITHSIZE + , m_pointPadding(other.pointPadding()) + , m_rawNodeList(other.rawNodeList()) +#endif { } @@ -76,6 +89,10 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other) m_innerURLElement = other.URLElement(); m_scrollbar = other.scrollbar(); m_isOverWidget = other.isOverWidget(); +#ifdef ANDROID_HITTEST_WITHSIZE + m_pointPadding = other.pointPadding(); + m_rawNodeList = other.rawNodeList(); +#endif return *this; } @@ -362,4 +379,50 @@ bool HitTestResult::isContentEditable() const return m_innerNonSharedNode->isContentEditable(); } +#ifdef ANDROID_HITTEST_WITHSIZE + +bool HitTestResult::intersects(int x, int y, const IntRect& other) const +{ + IntRect pointRect(x - m_pointPadding.width(), y - m_pointPadding.height(), 2 * m_pointPadding.width() + 1, 2* m_pointPadding.height() + 1); + return other.intersects(pointRect); +} + +bool HitTestResult::containedBy(int x, int y, const IntRect& other) const +{ + IntRect pointRect(x - m_pointPadding.width(), y - m_pointPadding.height(), 2 * m_pointPadding.width() + 1, 2* m_pointPadding.height() + 1); + return other.contains(pointRect); +} + +void HitTestResult::merge(const HitTestResult& other) +{ + if (!m_innerNode && other.innerNode()) { + m_innerNode = other.innerNode(); + m_innerNonSharedNode = other.innerNonSharedNode(); + m_localPoint = other.localPoint(); + m_innerURLElement = other.URLElement(); + m_scrollbar = other.scrollbar(); + m_isOverWidget = other.isOverWidget(); + } + + const Vector<RefPtr<Node> >& list = other.rawNodeList(); + Vector<RefPtr<Node> >::const_iterator last = list.end(); + for (Vector<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) + addRawNode(it->get()); +} + +void HitTestResult::addRawNode(Node* node) +{ + if (!node) + return; + + Vector<RefPtr<Node> >::const_iterator last = m_rawNodeList.end(); + for (Vector<RefPtr<Node> >::const_iterator it = m_rawNodeList.begin(); it != last; ++it) + if ((*it) == node) + return; + + m_rawNodeList.append(node); +} + +#endif // ANDROID_HITTEST_WITHSIZE + } // namespace WebCore diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h index d1906ba..0f45900 100644 --- a/WebCore/rendering/HitTestResult.h +++ b/WebCore/rendering/HitTestResult.h @@ -22,6 +22,10 @@ #include "IntPoint.h" #include "TextDirection.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include <IntSize.h> +#include <wtf/Vector.h> +#endif #include <wtf/RefPtr.h> namespace WebCore { @@ -76,6 +80,19 @@ public: bool isLiveLink() const; bool isContentEditable() const; +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult(const IntPoint&, const IntSize&); + + IntSize pointPadding() const { return m_pointPadding; } + bool isRegionTest() const { return !m_pointPadding.isEmpty(); } + bool intersects(int, int, const IntRect&) const; + bool containedBy(int, int, const IntRect&) const; + + void merge(const HitTestResult&); + void addRawNode(Node*); + const Vector<RefPtr<Node> >& rawNodeList() const { return m_rawNodeList; } +#endif + private: RefPtr<Node> m_innerNode; RefPtr<Node> m_innerNonSharedNode; @@ -85,6 +102,11 @@ private: RefPtr<Element> m_innerURLElement; RefPtr<Scrollbar> m_scrollbar; bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example). + +#ifdef ANDROID_HITTEST_WITHSIZE + IntSize m_pointPadding; + Vector<RefPtr<Node> > m_rawNodeList; +#endif }; String displayString(const String&, const Node*); diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 6ee610d..e31bf4f 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -607,7 +607,11 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re { IntRect overflowRect(visibleOverflowRect()); overflowRect.move(tx, ty); +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.intersects(x, y, overflowRect)) +#else if (!overflowRect.contains(x, y)) +#endif return false; // Check children first. @@ -620,8 +624,20 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re // Now check ourselves. IntRect rect(tx + m_x, ty + m_y, m_width, height()); +#ifdef ANDROID_HITTEST_WITHSIZE + if (visibleToHitTesting() && result.intersects(x, y, rect)) { +#else if (visibleToHitTesting() && rect.contains(x, y)) { +#endif renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space. +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(renderer()->node() || renderer()->isAnonymous()); + result.addRawNode(renderer()->node()); + if (!result.containedBy(x, y, rect)) + return false; + } +#endif return true; } diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 9c28b42..0c5df41 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -266,8 +266,20 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in return false; IntRect rect(tx + m_x, ty + m_y, m_width, height()); +#ifdef ANDROID_HITTEST_WITHSIZE + if (m_truncation != cFullTruncation && visibleToHitTesting() && result.intersects(x, y, rect)) { +#else if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.contains(x, y)) { +#endif renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(renderer()->node() || renderer()->isAnonymous()); + result.addRawNode(renderer()->node()); + if (!result.containedBy(x, y, rect)) + return false; + } +#endif return true; } return false; diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index cf4101b..f8c8b8d 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -3317,19 +3317,34 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Check if we need to do anything at all. IntRect overflowBox = visibleOverflowRect(); overflowBox.move(tx, ty); +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.intersects(_x, _y, overflowBox)) +#else if (!overflowBox.contains(_x, _y)) +#endif return false; } if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) { updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + // TODO: isPointInOverflowControl() doesn't handle region test yet. + if (result.isRegionTest()) { + ASSERT(node() || isAnonymous()); + result.addRawNode(node()); + } else +#endif return true; } // If we have clipping, then we can't have any spillout. bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer(); bool useClip = (hasControlClip() || useOverflowClip); +#ifdef ANDROID_HITTEST_WITHSIZE + bool checkChildren = !useClip || (hasControlClip() ? result.intersects(_x, _y, controlClipRect(tx, ty)) : result.intersects(_x, _y, overflowClipRect(tx, ty))); +#else bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y)); +#endif if (checkChildren) { // Hit test descendants first. int scrolledX = tx; @@ -3373,8 +3388,20 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Now hit test our background if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) { IntRect boundsRect(tx, ty, width(), height()); +#ifdef ANDROID_HITTEST_WITHSIZE + if (visibleToHitTesting() && result.intersects(_x, _y, boundsRect)) { +#else if (visibleToHitTesting() && boundsRect.contains(_x, _y)) { +#endif updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(node() || isAnonymous()); + result.addRawNode(node()); + if (!result.containedBy(_x, _y, boundsRect)) + return false; + } +#endif return true; } } @@ -3395,12 +3422,21 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r IntRect colRect = colRects->at(i); colRect.move(tx, ty); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.intersects(x, y, colRect)) { +#else if (colRect.contains(x, y)) { +#endif // The point is inside this column. // Adjust tx and ty to change where we hit test. int finalX = tx + currXOffset; int finalY = ty + currYOffset; +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest() && !result.containedBy(x, y, colRect)) + hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); + else +#endif return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction); } diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 9204b64..4c5d702 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -34,6 +34,9 @@ #include "htmlediting.h" #include "HTMLElement.h" #include "HTMLNames.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include "HitTestResult.h" +#endif #include "ImageBuffer.h" #include "FloatQuad.h" #include "Frame.h" @@ -556,10 +559,23 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result } } +#ifdef ANDROID_HITTEST_WITHSIZE + IntRect boundsRect = IntRect(tx, ty, width(), height()); + if (visibleToHitTesting() && action == HitTestForeground && result.intersects(xPos, yPos, boundsRect)) { +#else // Check our bounds next. For this purpose always assume that we can only be hit in the // foreground phase (which is true for replaced elements like images). if (visibleToHitTesting() && action == HitTestForeground && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) { +#endif updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(node() || isAnonymous()); + result.addRawNode(node()); + if (!result.containedBy(xPos, yPos, boundsRect)) + return false; + } +#endif return true; } diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 73cf73c..237dfb6 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -513,10 +513,18 @@ HTMLMapElement* RenderImage::imageMap() const bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult tempResult(result.point(), result.pointPadding()); +#else HitTestResult tempResult(result.point()); +#endif bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction); +#ifdef ANDROID_HITTEST_WITHSIZE + if (tempResult.innerNode() && node()) { +#else if (inside && node()) { +#endif if (HTMLMapElement* map = imageMap()) { IntRect contentBox = contentBoxRect(); float zoom = style()->effectiveZoom(); @@ -527,6 +535,10 @@ bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } } +#ifdef ANDROID_HITTEST_WITHSIZE + if (!inside && result.isRegionTest()) + result.merge(tempResult); +#endif if (inside) result = tempResult; return inside; diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index ea29087..37dbd38 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -2603,7 +2603,11 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (parent()) { IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects); // Go ahead and test the enclosing clip now. +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.intersects(hitTestPoint.x(), hitTestPoint.y(), clipRect)) +#else if (!clipRect.contains(hitTestPoint)) +#endif return 0; } @@ -2700,9 +2704,20 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont // Begin by walking our list of positive layers from highest z-index down to the lowest z-index. if (m_posZOrderList) { for (int i = m_posZOrderList->size() - 1; i >= 0; --i) { +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult tempResult(result.point(), result.pointPadding()); +#else HitTestResult tempResult(result.point()); +#endif RenderLayer* hitLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) + result.merge(tempResult); +#endif if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.isRegionTest()) +#endif result = tempResult; if (!depthSortDescendants) return hitLayer; @@ -2716,9 +2731,20 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (m_normalFlowList) { for (int i = m_normalFlowList->size() - 1; i >= 0; --i) { RenderLayer* currLayer = m_normalFlowList->at(i); +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult tempResult(result.point(), result.pointPadding()); +#else HitTestResult tempResult(result.point()); +#endif RenderLayer* hitLayer = currLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) + result.merge(tempResult); +#endif if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.isRegionTest()) +#endif result = tempResult; if (!depthSortDescendants) return hitLayer; @@ -2729,25 +2755,53 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont } // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.intersects(hitTestPoint.x(), hitTestPoint.y(), fgRect) && isSelfPaintingLayer()) { +#else if (fgRect.contains(hitTestPoint) && isSelfPaintingLayer()) { +#endif // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost. +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult tempResult(result.point(), result.pointPadding()); +#else HitTestResult tempResult(result.point()); +#endif if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) + result.merge(tempResult); + else +#endif result = tempResult; if (!depthSortDescendants) return this; // Foreground can depth-sort with descendant layers, so keep this as a candidate. candidateLayer = this; } +#ifdef ANDROID_HITTEST_WITHSIZE + else if (result.isRegionTest()) + result.merge(tempResult); +#endif } // Now check our negative z-index children. if (m_negZOrderList) { for (int i = m_negZOrderList->size() - 1; i >= 0; --i) { +#ifdef ANDROID_HITTEST_WITHSIZE + HitTestResult tempResult(result.point(), result.pointPadding()); +#else HitTestResult tempResult(result.point()); +#endif RenderLayer* hitLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) + result.merge(tempResult); +#endif if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (!result.isRegionTest()) +#endif result = tempResult; if (!depthSortDescendants) return hitLayer; @@ -2761,13 +2815,27 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont if (candidateLayer) return candidateLayer; +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.intersects(hitTestPoint.x(), hitTestPoint.y(), bgRect) && isSelfPaintingLayer()) { + HitTestResult tempResult(result.point(), result.pointPadding()); +#else if (bgRect.contains(hitTestPoint) && isSelfPaintingLayer()) { HitTestResult tempResult(result.point()); +#endif if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) + result.merge(tempResult); + else +#endif result = tempResult; return this; } +#ifdef ANDROID_HITTEST_WITHSIZE + else if (result.isRegionTest()) + result.merge(tempResult); +#endif } return 0; diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 9736874..3395347 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -30,6 +30,9 @@ #include "RenderLineBoxList.h" #include "InlineTextBox.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include "HitTestResult.h" +#endif #include "RenderArena.h" #include "RenderInline.h" #include "RenderView.h" @@ -230,14 +233,22 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq // contain the point. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. +#ifdef ANDROID_HITTEST_WITHSIZE + if ((y - result.pointPadding().height() >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y + result.pointPadding().height() < ty + firstLineBox()->root()->topVisibleOverflow())) +#else if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow())) +#endif return false; // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { +#ifdef ANDROID_HITTEST_WITHSIZE + if (y + result.pointPadding().height() >= ty + curr->root()->topVisibleOverflow() && y - result.pointPadding().height() < ty + curr->root()->bottomVisibleOverflow()) { +#else if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { +#endif bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 67a3b2a..6017513 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -26,6 +26,9 @@ #include "RenderSVGRoot.h" #include "GraphicsContext.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include "HitTestResult.h" +#endif #include "RenderSVGContainer.h" #include "RenderView.h" #include "SVGLength.h" @@ -313,6 +316,13 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { // FIXME: CSS/HTML assumes the local point is relative to the border box, right? updateHitTestResult(result, pointInBorderBox); +#ifdef ANDROID_HITTEST_WITHSIZE + // TODO: nodeAtFloatPoint() doesn't handle region test yet. + if (result.isRegionTest()) { + ASSERT(node() || isAnonymous()); + result.addRawNode(node()); + } else +#endif return true; } } diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 0a61a93..eac5c5d 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -31,6 +31,9 @@ #include "Document.h" #include "FixedTableLayout.h" #include "FrameView.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include "HitTestResult.h" +#endif #include "HTMLNames.h" #include "RenderLayer.h" #include "RenderTableCell.h" @@ -1202,7 +1205,11 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu ty += y(); // Check kids first. +#ifdef ANDROID_HITTEST_WITHSIZE + if (!hasOverflowClip() || result.intersects(xPos, yPos, overflowClipRect(tx, ty))) { +#else if (!hasOverflowClip() || overflowClipRect(tx, ty).contains(xPos, yPos)) { +#endif for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) { @@ -1213,8 +1220,21 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu } // Check our bounds next. +#ifdef ANDROID_HITTEST_WITHSIZE + IntRect boundsRect = IntRect(tx, ty, width(), height()); + if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && result.intersects(xPos, yPos, boundsRect)) { +#else if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) { +#endif updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty)); +#ifdef ANDROID_HITTEST_WITHSIZE + if (result.isRegionTest()) { + ASSERT(node() || isAnonymous()); + result.addRawNode(node()); + if (!result.containedBy(xPos, yPos, boundsRect)) + return false; + } +#endif return true; } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index e8ab4a4..e8f9cc4 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -28,6 +28,9 @@ #include "CachedImage.h" #include "Document.h" +#ifdef ANDROID_HITTEST_WITHSIZE +#include "HitTestResult.h" +#endif #include "HTMLNames.h" #include "RenderTableCell.h" #include "RenderTableCol.h" @@ -1259,7 +1262,11 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul tx += x(); ty += y(); +#ifdef ANDROID_HITTEST_WITHSIZE + if (hasOverflowClip() && !result.intersects(xPos, yPos, overflowClipRect(tx, ty))) +#else if (hasOverflowClip() && !overflowClipRect(tx, ty).contains(xPos, yPos)) +#endif return false; for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 15c75f1..2c53da4 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -378,6 +378,12 @@ bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res // Check to see if we are really over the widget itself (and not just in the border/padding area). if (inside && !hadResult && result.innerNode() == node()) result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); +#ifdef ANDROID_HITTEST_WITHSIZE + else if (result.isRegionTest() && !hadResult && result.innerNode() == node()) { + result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); + return false; + } +#endif return inside; } |