summaryrefslogtreecommitdiffstats
path: root/WebCore
diff options
context:
space:
mode:
authorGrace Kloba <klobag@google.com>2010-05-18 21:59:53 -0700
committerGrace Kloba <klobag@google.com>2010-05-24 21:41:25 -0700
commit17dcead8ee9edfa8f75e7e2d2284ed3c6f4bd403 (patch)
tree8d89d459030792e918c95900963217ec89287eab /WebCore
parent40a65b8dda8d56276893edcc25c957d13b3a9b77 (diff)
downloadexternal_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.h3
-rw-r--r--WebCore/page/EventHandler.cpp12
-rw-r--r--WebCore/page/EventHandler.h4
-rw-r--r--WebCore/rendering/EllipsisBox.cpp13
-rw-r--r--WebCore/rendering/HitTestResult.cpp63
-rw-r--r--WebCore/rendering/HitTestResult.h22
-rw-r--r--WebCore/rendering/InlineFlowBox.cpp16
-rw-r--r--WebCore/rendering/InlineTextBox.cpp12
-rw-r--r--WebCore/rendering/RenderBlock.cpp36
-rw-r--r--WebCore/rendering/RenderBox.cpp16
-rw-r--r--WebCore/rendering/RenderImage.cpp12
-rw-r--r--WebCore/rendering/RenderLayer.cpp68
-rw-r--r--WebCore/rendering/RenderLineBoxList.cpp11
-rw-r--r--WebCore/rendering/RenderSVGRoot.cpp10
-rw-r--r--WebCore/rendering/RenderTable.cpp20
-rw-r--r--WebCore/rendering/RenderTableSection.cpp7
-rw-r--r--WebCore/rendering/RenderWidget.cpp6
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;
}