COMMIT_MESSAGE

 12010-07-21 Grace Kloba <klobag@gmail.com> , Antonio Gomes <tonikitoo@webkit.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Enhance the hit testing to take a rectangle instead of a point
 6 https://bugs.webkit.org/show_bug.cgi?id=40197
 7
 8 The primary goal of this change is to provide mechanisms for more precise tap
 9 actions by the users on mobile devices.
 10
 11 Patch extends the hit testing system to work considering a rectangular area
 12 as input instead of a point, when applicable. For that, the HitTestResult class
 13 was modified to take a padding (IntSize). The padding specifies a fuzzy range for
 14 accepting input events in pixels coordinates for both vertical and horizontal
 15 orientations. In other words, it tells how much to expand the search rect
 16 around a supposed touch point.
 17
 18 If it is negative, hit testing will behavior as the current point based hit testing,
 19 and methods are no-op'ed to not regress this common behavior performance-wise.
 20 When non negative IntSize is provided, the hit test result will keep record of all
 21 nodes that intersect the built up test area. The logic will continue searching when it
 22 finds a candidate until the rectangle is fully enclosed by the boundaries of a candidate.
 23 The result will be a list of nodes in the z-order they are hit-tested.
 24 Caller will decide how to process them.
 25
 26 In order to expose the functionality, the patch:
 27
 28 - Adds a nodesFromRect method to the Document class, exposing the funcionality
 29 to the DOM. Method returns a NodeList with all nodes that intersect the given
 30 hit-tested area.
 31 - Extends hitTestResultAtPoint method of the EventHandler with an extra 'padding'
 32 parameter, defaulting to IntSize(-1, -1). The rect-based hit test is performed when a
 33 non-negative padding is passed in.
 34
 35 Test: fast/dom/nodesFromRect-basic.html
 36
 37 * WebCore.base.exp:
 38 * dom/Document.cpp:
 39 (WebCore::Document::nodesFromRect): This method exposes the rect based funcionality to
 40 the DOM. It works similarly to elementFromPoint, however receiving a rectangular area
 41 as input instead of a point, and returning a z-index ordered list of nodes (not elements)
 42 whose area intersect the hit test rect.
 43 * dom/Document.h: Ditto.
 44 * dom/Document.idl: Ditto.
 45 * page/EventHandler.cpp:
 46 (WebCore::EventHandler::hitTestResultAtPoint): The funcionality is also exposed through this
 47 method. Patch adds a additional IntSize parameter to work as the padding area, building up
 48 the hit test rect.
 49 * page/EventHandler.h: Ditto.
 50 * rendering/HitTestResult.cpp:
 51 (WebCore::HitTestResult::HitTestResult): Rect based hit test constructor. Receives a
 52 padding IntSize as parameter. It can be (0,0).
 53 (WebCore::HitTestResult::operator=): Modified to assign the m_rectBasedTestResult as well.
 54 (WebCore::HitTestResult::append): Merge to HitTestResult objects in a way that the
 55 list node's of both objects get amended.
 56 (WebCore::HitTestResult::addNodeToRectBasedTestResult): Adds a given Node to the list of
 57 hit nodes.
 58 * rendering/HitTestResult.h:
 59 (WebCore::HitTestResult::padding): Returns the padding as an IntSize.
 60 (WebCore::HitTestResult::isRectBasedTest): Returns if the HitTestResult is rect based or not.
 61 (WebCore::HitTestResult::.rectBasedTestResult): Returns the list nodes hit.
 62 (WebCore::HitTestResult::rectFromPoint): Returns the hit test rect given the hit test point
 63 and padding.
 64 * rendering/RenderLayer.cpp:
 65 (WebCore::RenderLayer::hitTestLayer):
 66 (WebCore::RenderLayer::hitTestList):
 67 (WebCore::RenderLayer::hitTestChildLayerColumns):
 68 * rendering/EllipsisBox.cpp:
 69 (WebCore::EllipsisBox::nodeAtPoint): Method is modified to support rect based hit test extension.
 70 Now it not just checks if the boundary of the node being hit-tested contains a hit test point, but
 71 instead it checks if the boundary of the node intersects a hit test rect. It is implemented so
 72 that the common case (point based hit test) works as previously.
 73 * rendering/InlineFlowBox.cpp:
 74 (WebCore::InlineFlowBox::nodeAtPoint): Ditto.
 75 * rendering/InlineTextBox.cpp:
 76 (WebCore::InlineTextBox::nodeAtPoint): Ditto.
 77 * rendering/RenderBlock.cpp:
 78 (WebCore::RenderBlock::nodeAtPoint): Ditto.
 79 (WebCore::RenderBlock::hitTestColumns): Ditto.
 80 * rendering/RenderBox.cpp:
 81 (WebCore::RenderBox::nodeAtPoint): Ditto.
 82 * rendering/RenderImage.cpp:
 83 (WebCore::RenderImage::nodeAtPoint): Ditto.
 84 * rendering/RenderLineBoxList.cpp:
 85 (WebCore::RenderLineBoxList::hitTest):
 86 * rendering/RenderSVGRoot.cpp:
 87 (WebCore::RenderSVGRoot::nodeAtPoint): Ditto.
 88 * rendering/RenderTable.cpp:
 89 (WebCore::RenderTable::nodeAtPoint): Ditto.
 90 * rendering/RenderTableSection.cpp:
 91 (WebCore::RenderTableSection::nodeAtPoint): Ditto.
 92 * rendering/RenderWidget.cpp:
 93 (WebCore::RenderWidget::nodeAtPoint): Ditto.
 94
 95amend me - core

LayoutTests/ChangeLog

 12010-07-21 Antonio Gomes <tonikitoo@webkit.org> , Grace Kloba <klobag@gmail.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Enhance the hit testing to take a rectangle instead of a point
 6 https://bugs.webkit.org/show_bug.cgi?id=40197
 7
 8 * fast/dom/nodesFromRect-basic-expected.txt: Added.
 9 * fast/dom/nodesFromRect-basic.html: Added.
 10
1112010-07-22 Kent Tamura <tkent@chromium.org>
212
313 Reviewed by Darin Adler.

LayoutTests/fast/dom/Window/window-properties-expected.txt

@@window.Document.prototype.isSameNode [function]
628628window.Document.prototype.isSupported [function]
629629window.Document.prototype.lookupNamespaceURI [function]
630630window.Document.prototype.lookupPrefix [function]
 631window.Document.prototype.nodesFromRect [function]
631632window.Document.prototype.normalize [function]
632633window.Document.prototype.queryCommandEnabled [function]
633634window.Document.prototype.queryCommandIndeterm [function]

LayoutTests/fast/dom/nodesFromRect-basic-expected.txt

 1PASS successfullyParsed is true
 2
 3TEST COMPLETE
 4PASS All correct nodes found for rect [53,71], [0,0]
 5PASS All correct nodes found for rect [53,71], [10,0]
 6PASS All correct nodes found for rect [53,71], [0,10]
 7PASS All correct nodes found for rect [53,71], [10,10]
 8PASS All correct nodes found for rect [152,105], [0,10]
 9PASS All correct nodes found for rect [152,105], [10,0]
 10PASS All correct nodes found for rect [152,105], [10,10]
 11PASS All correct nodes found for rect [153,193], [0,0]
 12PASS All correct nodes found for rect [153,193], [20,0]
 13PASS All correct nodes found for rect [153,193], [0,20]
 14PASS All correct nodes found for rect [144,183], [0,0]
 15PASS All correct nodes found for rect [144,183], [0,1]
 16PASS All correct nodes found for rect [144,183], [1,0]
 17PASS All correct nodes found for rect [144,183], [1,1]
 18PASS All correct nodes found for rect [77,240], [0,0]
 19PASS All correct nodes found for rect [77,240], [10,0]
 20PASS All correct nodes found for rect [77,240], [0,10]
 21PASS All correct nodes found for rect [77,240], [10,10]
 22PASS All correct nodes found for rect [39,212], [0,0]
 23PASS All correct nodes found for rect [39,212], [0,10]
 24PASS All correct nodes found for rect [39,212], [10,0]
 25PASS All correct nodes found for rect [39,212], [10,10]
 26

LayoutTests/fast/dom/nodesFromRect-basic.html

 1<html>
 2<head>
 3 <title>Document::nodesFromRect test - bug 40197</title>
 4 <style type="text/css"> @import "resources/nodesFromRect.css"; </style>
 5 <script src="../js/resources/js-test-pre.js"></script>
 6 <script src="resources/nodesFromRect.js"></script>
 7 <script type="application/javascript">
 8 function runTest()
 9 {
 10 if (window.layoutTestController) {
 11 layoutTestController.dumpAsText();
 12 layoutTestController.waitUntilDone();
 13 }
 14
 15 var e = {};
 16
 17 // Set up shortcut access to elements
 18 e['html'] = document.getElementsByTagName("html")[0];
 19 ['h1', 'd1', 'd2', 'p1', 'p2', 'p3', 'p4', 'p5', 'span', 'body'].forEach(function(a) {
 20 e[a] = document.getElementById(a);
 21 });
 22
 23 window.scrollTo(0, 0);
 24
 25 check(53, 71, 0, 0, [e.body]);
 26 check(53, 71, 10, 0, [e.p3, e.body]);
 27 check(53, 71, 0, 10, [e.d1, e.h1, e.body]);
 28 check(53, 71, 10, 10, [e.p3, e.d1, e.h1, e.body]);
 29
 30 check(152, 105, 0, 10, [e.p3, e.body]);
 31 check(152, 105, 10, 0, [e.p4, e.d1, e.body]);
 32 check(152, 105, 10, 10, [e.p4, e.p3, e.d1, e.body]);
 33
 34 // e.p1 is invisible and shouldn't appear:
 35 check(153,193,0,0,[e.p5]);
 36 // NOTE: [e.p5, e.d2]) should be returned if we did not stop
 37 // at e.p5, which fully encloses the target rect.
 38 check(153,193,20,0, [e.p5]);
 39 check(153,193,0,20, [e.p5, e.body]);
 40
 41 // Precise pixel checks:
 42 check(144, 183, 0, 0, [e.body]);
 43 check(144, 183, 0, 1, [e.p5, e.body]);
 44 check(144, 183, 1, 0, [e.d2, e.body]);
 45 check(144, 183, 1, 1, [e.p5, e.d2, e.body]);
 46 check(77, 240, 0, 0, [e.p2]);
 47 check(77, 240, 10, 0, [e.p2]);
 48 check(77, 240, 0, 10, [e.p5, e.span, e.p2]);
 49 check(77, 240, 10, 10, [e.p5, e.span, e.p2]);
 50
 51 // Expanding area checks:
 52 check(39, 212, 0, 0, [e.body]);
 53 check(39, 212, 0, 10, [e.d2, e.p2, e.body]);
 54 check(39, 212, 10, 0, [e.p5, e.body]);
 55 check(39, 212, 10, 10, [e.p5, e.d2, e.p2, e.body]);
 56
 57 if (window.layoutTestController)
 58 layoutTestController.notifyDone();
 59 }
 60
 61 window.onload = runTest;
 62 </script>
 63</head>
 64<body id="body">
 65 <h1 id="h1"></h1>
 66 <div id="d1"></div>
 67
 68 <!-- floated element -->
 69 <div id="d2" style="float: left"></div>
 70
 71 <!-- hidden element -->
 72 <p id="p1" style="float: left; visibility: hidden"></p>
 73
 74 <p id="p2" style="clear: left"><span id="span"></span></p>
 75
 76 <!-- absolute position -->
 77 <p id="p3" style="position:absolute; top: 10px; left:50px; height:50px;"></p>
 78
 79 <!-- fixed position -->
 80 <p id="p4" style="position: fixed; top: 30px; left: 150px; height: 50px; background-color: blue;"></p>
 81
 82 <!-- relative position -->
 83 <p id="p5" style="position:relative; top: -100px; left: 30px; margin-bottom: -70px; background-color: green"></p>
 84
 85 <span id="console"></span>
 86 <script src="../js/resources/js-test-post.js"></script>
 87</body>
 88</html>
 89

LayoutTests/fast/dom/resources/nodesFromRect.css

 1body {
 2 margin: 8px;
 3 padding: 0;
 4}
 5
 6h1, div, p, iframe {
 7 display: block;
 8 width: 100px;
 9 height: 30px;
 10 border: 3px solid black;
 11 padding: 10px;
 12 margin: 10px;
 13}
 14
 15#span {
 16 display: block;
 17 width: 100px;
 18 height: 30px;
 19 border: 3px solid black;
 20 padding: 10px;
 21 margin: 10px;
 22 display: inline-block;
 23}
 24
 25#iframe1 {
 26 height: 100px;
 27 margin-top: 60px;
 28}
 29
 30#p6 {
 31 height: 50px;
 32 margin-top: 30px;
 33}
 34
 35#transf {
 36 margin-top: 60px;
 37 -webkit-transform: rotate(-45deg);
 38}
 39
 40#decimal {
 41 position: relative;
 42 left: 0.5px;
 43 top: 50.5px;
 44}

LayoutTests/fast/dom/resources/nodesFromRect.js

 1/*
 2 * Contributors:
 3 * * Antonio Gomes <tonikitoo@webkit.org>
 4 **/
 5
 6function check(x, y, hPadding, vPadding, list)
 7{
 8 /*
 9 NodeList nodesFromRect(in long x,
 10 in long y,
 11 in long hPadding,
 12 in long vPadding,
 13 in boolean ignoreClipping);
 14 */
 15 var nodes = document.nodesFromRect(x, y, hPadding, vPadding, true /* ignoreClipping */);
 16
 17 if (nodes.length != list.length) {
 18 testFailed("Different number of nodes for rect" +
 19 "[" + x + "," + y + "], " +
 20 "[" + hPadding + "," + vPadding + "]: '" + list.length + "' vs '" + nodes.length + "'");
 21 return;
 22 }
 23
 24 for (var i = 0; i < nodes.length; i++) {
 25 if (nodes[i] != list[i]) {
 26 testFailed("Unexpected node #" + i + " for rect " +
 27 "[" + x + "," + y + "], " +
 28 "[" + hPadding + "," + vPadding + "]" + " - " + nodes[i]);
 29 return;
 30 }
 31 }
 32
 33 testPassed("All correct nodes found for rect " +
 34 "[" + x + "," + y + "], " +
 35 "[" + hPadding + "," + vPadding + "]");
 36}
 37
 38function getCenterFor(element)
 39{
 40 var rect = element.getBoundingClientRect();
 41 return { x : parseInt((rect.left + rect.right) / 2) , y : parseInt((rect.top + rect.bottom) / 2)};
 42}
 43
 44var successfullyParsed = true;

LayoutTests/platform/qt/fast/dom/Window/window-properties-expected.txt

@@window.Document.prototype.isSameNode [function]
628628window.Document.prototype.isSupported [function]
629629window.Document.prototype.lookupNamespaceURI [function]
630630window.Document.prototype.lookupPrefix [function]
 631window.Document.prototype.nodesFromRect [function]
631632window.Document.prototype.normalize [function]
632633window.Document.prototype.queryCommandEnabled [function]
633634window.Document.prototype.queryCommandIndeterm [function]

WebCore/ChangeLog

 12010-07-21 Grace Kloba <klobag@gmail.com> , Antonio Gomes <tonikitoo@webkit.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Enhance the hit testing to take a rectangle instead of a point
 6 https://bugs.webkit.org/show_bug.cgi?id=40197
 7
 8 The primary goal of this change is to provide mechanisms for more precise tap
 9 actions by the users on mobile devices.
 10
 11 Patch extends the hit testing system to work considering a rectangular area
 12 as input instead of a point, when applicable. For that, the HitTestResult class
 13 was modified to take a padding (IntSize). The padding specifies a fuzzy range for
 14 accepting input events in pixels coordinates for both vertical and horizontal
 15 orientations. In other words, it tells how much to expand the search rect
 16 around a supposed touch point.
 17
 18 If it is negative, hit testing will behavior as the current point based hit testing,
 19 and methods are no-op'ed to not regress this common behavior performance-wise.
 20 When non negative IntSize is provided, the hit test result will keep record of all
 21 nodes that intersect the built up test area. The logic will continue searching when it
 22 finds a candidate until the rectangle is fully enclosed by the boundaries of a candidate.
 23 The result will be a list of nodes in the z-order they are hit-tested.
 24 Caller will decide how to process them.
 25
 26 In order to expose the functionality, the patch:
 27
 28 - Adds a nodesFromRect method to the Document class, exposing the funcionality
 29 to the DOM. Method returns a NodeList with all nodes that intersect the given
 30 hit-tested area.
 31 - Extends hitTestResultAtPoint method of the EventHandler with an extra 'padding'
 32 parameter, defaulting to IntSize(-1, -1). The rect-based hit test is performed when a
 33 non-negative padding is passed in.
 34
 35 Test: fast/dom/nodesFromRect-basic.html
 36
 37 * WebCore.base.exp:
 38 * dom/Document.cpp:
 39 (WebCore::Document::nodesFromRect): This method exposes the rect based funcionality to
 40 the DOM. It works similarly to elementFromPoint, however receiving a rectangular area
 41 as input instead of a point, and returning a z-index ordered list of nodes (not elements)
 42 whose area intersect the hit test rect.
 43 * dom/Document.h: Ditto.
 44 * dom/Document.idl: Ditto.
 45 * page/EventHandler.cpp:
 46 (WebCore::EventHandler::hitTestResultAtPoint): The funcionality is also exposed through this
 47 method. Patch adds a additional IntSize parameter to work as the padding area, building up
 48 the hit test rect.
 49 * page/EventHandler.h: Ditto.
 50 * rendering/HitTestResult.cpp:
 51 (WebCore::HitTestResult::HitTestResult): Rect based hit test constructor. Receives a
 52 padding IntSize as parameter. It can be (0,0).
 53 (WebCore::HitTestResult::operator=): Modified to assign the m_rectBasedTestResult as well.
 54 (WebCore::HitTestResult::append): Merge to HitTestResult objects in a way that the
 55 list node's of both objects get amended.
 56 (WebCore::HitTestResult::addNodeToRectBasedTestResult): Adds a given Node to the list of
 57 hit nodes.
 58 * rendering/HitTestResult.h:
 59 (WebCore::HitTestResult::padding): Returns the padding as an IntSize.
 60 (WebCore::HitTestResult::isRectBasedTest): Returns if the HitTestResult is rect based or not.
 61 (WebCore::HitTestResult::.rectBasedTestResult): Returns the list nodes hit.
 62 (WebCore::HitTestResult::rectFromPoint): Returns the hit test rect given the hit test point
 63 and padding.
 64 * rendering/RenderLayer.cpp:
 65 (WebCore::RenderLayer::hitTestLayer):
 66 (WebCore::RenderLayer::hitTestList):
 67 (WebCore::RenderLayer::hitTestChildLayerColumns):
 68 * rendering/EllipsisBox.cpp:
 69 (WebCore::EllipsisBox::nodeAtPoint): Method is modified to support rect based hit test extension.
 70 Now it not just checks if the boundary of the node being hit-tested contains a hit test point, but
 71 instead it checks if the boundary of the node intersects a hit test rect. It is implemented so
 72 that the common case (point based hit test) works as previously.
 73 * rendering/InlineFlowBox.cpp:
 74 (WebCore::InlineFlowBox::nodeAtPoint): Ditto.
 75 * rendering/InlineTextBox.cpp:
 76 (WebCore::InlineTextBox::nodeAtPoint): Ditto.
 77 * rendering/RenderBlock.cpp:
 78 (WebCore::RenderBlock::nodeAtPoint): Ditto.
 79 (WebCore::RenderBlock::hitTestColumns): Ditto.
 80 * rendering/RenderBox.cpp:
 81 (WebCore::RenderBox::nodeAtPoint): Ditto.
 82 * rendering/RenderImage.cpp:
 83 (WebCore::RenderImage::nodeAtPoint): Ditto.
 84 * rendering/RenderLineBoxList.cpp:
 85 (WebCore::RenderLineBoxList::hitTest):
 86 * rendering/RenderSVGRoot.cpp:
 87 (WebCore::RenderSVGRoot::nodeAtPoint): Ditto.
 88 * rendering/RenderTable.cpp:
 89 (WebCore::RenderTable::nodeAtPoint): Ditto.
 90 * rendering/RenderTableSection.cpp:
 91 (WebCore::RenderTableSection::nodeAtPoint): Ditto.
 92 * rendering/RenderWidget.cpp:
 93 (WebCore::RenderWidget::nodeAtPoint): Ditto.
 94
1952010-07-22 Jon Honeycutt <jhoneycutt@apple.com>
296
397 Windows build fix.

WebCore/WebCore.exp.in

@@__ZN7WebCore12EventHandler14scrollOverflowENS_15ScrollDirectionENS_17ScrollGranu
216216__ZN7WebCore12EventHandler15sendScrollEventEv
217217__ZN7WebCore12EventHandler16handleWheelEventERNS_18PlatformWheelEventE
218218__ZN7WebCore12EventHandler20handleTextInputEventERKNS_6StringEPNS_5EventEbb
219 __ZN7WebCore12EventHandler20hitTestResultAtPointERKNS_8IntPointEbbNS_17HitTestScrollbarsEj
 219__ZN7WebCore12EventHandler20hitTestResultAtPointERKNS_8IntPointEbbNS_17HitTestScrollbarsEjRKNS_7IntSizeE
220220__ZN7WebCore12EventHandler21handleMousePressEventERKNS_18PlatformMouseEventE
221221__ZN7WebCore12EventHandler23handleMouseReleaseEventERKNS_18PlatformMouseEventE
222222__ZN7WebCore12EventHandler27capsLockStateMayHaveChangedEv

WebCore/dom/Document.cpp

119119#include "SegmentedString.h"
120120#include "SelectionController.h"
121121#include "Settings.h"
 122#include "StaticHashSetNodeList.h"
122123#include "StringBuffer.h"
123124#include "StyleSheetList.h"
124125#include "TextEvent.h"

@@namespace WebCore {
208209using namespace HTMLNames;
209210
210211// #define INSTRUMENT_LAYOUT_SCHEDULING 1
 212// #define DUMP_HITTEST_RESULT 1
211213
212214// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
213215// FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high

@@KURL Document::baseURI() const
10031005 return m_baseURL;
10041006}
10051007
 1008#ifdef DUMP_HITTEST_RESULT
 1009void static dumpHitTestResult(const HitTestResult& result)
 1010{
 1011 ListHashSet<RefPtr<Node> > list = result.rectBasedTestResult();
 1012 printf("(%s) - {x=%d y=%d hPadding=%d vPadding=%d}\n",
 1013 __FUNCTION__, result.point().x(), result.point().y(), result.padding().width(), result.padding().height());
 1014 printf("List size:%d\n", list.size());
 1015
 1016 unsigned count = 0;
 1017 ListHashSet<RefPtr<Node> >::const_iterator it = list.begin();
 1018 ListHashSet<RefPtr<Node> >::const_iterator end = list.end();
 1019 for ( ; it != end ; ++it) {
 1020 printf("%d) ", ++count);
 1021 Node* node = (*it).get();
 1022 if (node->isElementNode()) {
 1023 if (node->hasID())
 1024 printf("Hit element <%s>, id='%s'\n", node->nodeName().utf8().data(), static_cast<Element*>(node)->getAttribute("id").string().utf8().data());
 1025 else
 1026 printf("Hit element <%s>, NO ID!'\n", node->nodeName().utf8().data());
 1027 } else if (node->isTextNode())
 1028 printf("Text node hit. Content:'%s'\n", node->textContent().utf8().data());
 1029 else
 1030 printf("Hit node <%s>\n", node->nodeName().utf8().data());
 1031 }
 1032 printf("\n");
 1033}
 1034#endif
 1035
 1036// FIXME: We need to discuss the DOM API here at some point. Ideas:
 1037// * making it receive a rect as parameter, i.e. nodesFromRect(x, y, w, h);
 1038// * making it receive the expading size of each direction separately,
 1039// i.e. nodesFromRect(x, y, topSize, rightSize, bottomSize, leftSize);
 1040PassRefPtr<NodeList> Document::nodesFromRect(int centerX, int centerY, int hPadding, int vPadding, bool ignoreClipping) const
 1041{
 1042 // FIXME: Share code between this, elementFromPoint and caretRangeFromPoint.
 1043 if (!renderer())
 1044 return 0;
 1045 Frame* frame = this->frame();
 1046 if (!frame)
 1047 return 0;
 1048 FrameView* frameView = frame->view();
 1049 if (!frameView)
 1050 return 0;
 1051
 1052 float zoomFactor = frameView->pageZoomFactor();
 1053 IntPoint point = roundedIntPoint(FloatPoint(centerX * zoomFactor + view()->scrollX(), centerY * zoomFactor + view()->scrollY()));
 1054 IntSize padding(hPadding, vPadding);
 1055
 1056 int type = HitTestRequest::ReadOnly | HitTestRequest::Active;
 1057
 1058 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
 1059 if (ignoreClipping)
 1060 type |= HitTestRequest::IgnoreClipping;
 1061 else if (!frameView->visibleContentRect().intersects(IntRect(point, padding)))
 1062 return 0;
 1063
 1064 HitTestRequest request(type);
 1065 HitTestResult result(point, padding);
 1066 renderView()->layer()->hitTest(request, result);
 1067
 1068#ifdef DUMP_HITTEST_RESULT
 1069 dumpHitTestResult(result);
 1070#endif
 1071
 1072 return StaticHashSetNodeList::adopt(result.rectBasedTestResult());
 1073}
 1074
10061075Element* Document::elementFromPoint(int x, int y) const
10071076{
10081077 // FIXME: Share code between this and caretRangeFromPoint.

WebCore/dom/Document.h

@@public:
302302 bool hasElementWithId(AtomicStringImpl* id) const;
303303 bool containsMultipleElementsWithId(const AtomicString& elementId) { return m_duplicateIds.contains(elementId.impl()); }
304304
 305 /**
 306 * Retrieve all nodes that intersect a rect in the window's document, until it is fully enclosed by
 307 * the boundaries of node.
 308 *
 309 * @param centerX x reference for the rectangle in CSS pixels
 310 * @param centerY y reference for the rectangle in CSS pixels
 311 * @param hPadding How much to expand the rectangle horizontally
 312 * @param vPadding How much to expand the rectangle vertically
 313 * @param ignoreClipping whether or not to ignore the root scroll frame when retrieving the element.
 314 * If false, this method returns null for coordinates outside of the viewport.
 315 */
 316 PassRefPtr<NodeList> nodesFromRect(int centerX, int centerY, int hPadding, int vPadding, bool ignoreClipping) const;
305317 Element* elementFromPoint(int x, int y) const;
306318 PassRefPtr<Range> caretRangeFromPoint(int x, int y);
307319

WebCore/dom/Document.idl

@@module core {
186186 readonly attribute [ConvertNullStringTo=Undefined] DOMString defaultCharset;
187187 readonly attribute [ConvertNullStringTo=Undefined] DOMString readyState;
188188
 189
 190 NodeList nodesFromRect(in long x, in long y, in long hPadding, in long vPadding, in boolean ignoreClipping);
189191 Element elementFromPoint(in long x, in long y);
190192 Range caretRangeFromPoint(in long x, in long y);
191193

WebCore/page/EventHandler.cpp

@@void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
863863}
864864#endif // ENABLE(DRAG_SUPPORT)
865865
866 HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, HitTestRequest::HitTestRequestType hitType)
 866HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, HitTestRequest::HitTestRequestType hitType, const IntSize& padding)
867867{
868  HitTestResult result(point);
 868 HitTestResult result(point, padding);
869869 if (!m_frame->contentRenderer())
870870 return result;
871871 if (ignoreClipping)

@@HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
886886 FrameView* view = static_cast<FrameView*>(widget);
887887 IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(),
888888 result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop());
889  HitTestResult widgetHitTestResult(widgetPoint);
 889 HitTestResult widgetHitTestResult(widgetPoint, padding);
890890 frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult);
891891 result = widgetHitTestResult;
892892

@@HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
908908 if (resultView && mainView) {
909909 IntPoint windowPoint = resultView->contentsToWindow(result.point());
910910 IntPoint mainFramePoint = mainView->windowToContents(windowPoint);
911  result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping);
 911 result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping, testScrollbars, hitType, padding);
912912 }
913913 }
914914 }

WebCore/page/EventHandler.h

@@public:
106106
107107 void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);
108108
109  HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false, HitTestScrollbars scrollbars = DontHitTestScrollbars, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active);
 109 HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent,
 110 bool ignoreClipping = false,
 111 HitTestScrollbars scrollbars = DontHitTestScrollbars,
 112 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active,
 113 const IntSize& padding = IntSize(-1, -1));
110114
111115 bool mousePressed() const { return m_mousePressed; }
112116 void setMousePressed(bool pressed) { m_mousePressed = pressed; }

WebCore/rendering/EllipsisBox.cpp

@@bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
113113 }
114114 }
115115
116  if (visibleToHitTesting() && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
 116 IntRect boundsRect = IntRect(tx, ty, m_width, m_height);
 117 if (visibleToHitTesting() && boundsRect.intersects(result.rectFromPoint(x, y))) {
117118 renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
118  return true;
 119 if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, boundsRect))
 120 return true;
119121 }
120122
121123 return false;

WebCore/rendering/HitTestResult.cpp

@@using namespace HTMLNames;
4949HitTestResult::HitTestResult(const IntPoint& point)
5050 : m_point(point)
5151 , m_isOverWidget(false)
 52 , m_padding(IntSize(-1, -1))
 53 , m_isRectBased(false)
5254{
5355}
5456
 57HitTestResult::HitTestResult(const IntPoint& centerPoint, const IntSize& padding)
 58 : m_point(centerPoint)
 59 , m_isOverWidget(false)
 60 , m_padding(padding)
 61{
 62 m_isRectBased = padding.width() >= 0 && padding.height() >= 0;
 63}
 64
5565HitTestResult::HitTestResult(const HitTestResult& other)
5666 : m_innerNode(other.innerNode())
5767 , m_innerNonSharedNode(other.innerNonSharedNode())

@@HitTestResult::HitTestResult(const HitTestResult& other)
6070 , m_innerURLElement(other.URLElement())
6171 , m_scrollbar(other.scrollbar())
6272 , m_isOverWidget(other.isOverWidget())
 73 , m_padding(other.padding())
6374{
 75 if (m_isRectBased = other.isRectBasedTest()) {
 76 // Only copy the ListHashSet in case of rect hit test.
 77 // It is an expensive operation and unneeded in the common point based case.
 78 m_rectBasedTestResult = other.rectBasedTestResult();
 79 }
6480}
6581
6682HitTestResult::~HitTestResult()

@@HitTestResult& HitTestResult::operator=(const HitTestResult& other)
7692 m_innerURLElement = other.URLElement();
7793 m_scrollbar = other.scrollbar();
7894 m_isOverWidget = other.isOverWidget();
 95 m_padding = other.padding();
 96 if (m_isRectBased = other.isRectBasedTest()) {
 97 // Only copy the ListHashSet in case of rect hit test.
 98 // It is an expensive operation and unneeded in the common point based case.
 99 m_rectBasedTestResult = other.rectBasedTestResult();
 100 }
79101 return *this;
80102}
81103

@@bool HitTestResult::isContentEditable() const
362384 return m_innerNonSharedNode->isContentEditable();
363385}
364386
 387bool HitTestResult::addNodeToRectBasedTestResult(Node* node, int x, int y, const IntRect& rect)
 388{
 389 // If it is not a rect-based hit test, this method has to be no-op.
 390 // Return false, so the hit test stops.
 391 if (!isRectBasedTest())
 392 return false;
 393
 394 // If node is null, return true so the hit test can continue.
 395 if (!node)
 396 return true;
 397
 398 node = node->shadowAncestorNode();
 399 m_rectBasedTestResult.add(node);
 400
 401 return !rect.contains(rectFromPoint(x, y));
 402}
 403
 404void HitTestResult::append(const HitTestResult& other)
 405{
 406 ASSERT(isRectBasedTest() && other.isRectBasedTest());
 407
 408 if (!m_innerNode && other.innerNode()) {
 409 m_innerNode = other.innerNode();
 410 m_innerNonSharedNode = other.innerNonSharedNode();
 411 m_localPoint = other.localPoint();
 412 m_innerURLElement = other.URLElement();
 413 m_scrollbar = other.scrollbar();
 414 m_isOverWidget = other.isOverWidget();
 415 }
 416
 417 const ListHashSet<RefPtr<Node> >& list = other.rectBasedTestResult();
 418 ListHashSet<RefPtr<Node> >::const_iterator last = list.end();
 419 for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it)
 420 m_rectBasedTestResult.add(it->get());
 421}
 422
365423} // namespace WebCore

WebCore/rendering/HitTestResult.h

2121#define HitTestResult_h
2222
2323#include "IntPoint.h"
 24#include "IntRect.h"
 25#include "IntSize.h"
2426#include "TextDirection.h"
 27#include <wtf/ListHashSet.h>
2528#include <wtf/RefPtr.h>
2629
2730namespace WebCore {

@@class String;
3841class HitTestResult {
3942public:
4043 HitTestResult(const IntPoint&);
 44 // Pass a non-negative IntSize value as padding to perform a rect-based hit test.
 45 HitTestResult(const IntPoint& centerPoint, const IntSize& padding);
4146 HitTestResult(const HitTestResult&);
4247 ~HitTestResult();
4348 HitTestResult& operator=(const HitTestResult&);

@@public:
7681 bool isLiveLink() const;
7782 bool isContentEditable() const;
7883
 84 // Rect-based hit test related methods.
 85 bool isRectBasedTest() const { return m_isRectBased; }
 86 IntRect rectFromPoint(int x, int y) const;
 87 IntRect rectFromPoint(const IntPoint&) const;
 88 IntSize padding() const { return m_padding; }
 89 int paddingWidth() const { return m_padding.width() >= 0 ? m_padding.width() : 0; }
 90 int paddingHeight() const { return m_padding.height() >= 0 ? m_padding.height() : 0; }
 91 // Returns true if it is rect-based hit test and needs to continue until the rect is fully
 92 // enclosed by the boundaries of a node.
 93 bool addNodeToRectBasedTestResult(Node*, int x, int y, const IntRect& rect = IntRect());
 94 const ListHashSet<RefPtr<Node> >& rectBasedTestResult() const { return m_rectBasedTestResult; }
 95 void append(const HitTestResult&);
 96
7997private:
 98
8099 RefPtr<Node> m_innerNode;
81100 RefPtr<Node> m_innerNonSharedNode;
82101 IntPoint m_point;

@@private:
85104 RefPtr<Element> m_innerURLElement;
86105 RefPtr<Scrollbar> m_scrollbar;
87106 bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example).
 107 IntSize m_padding;
 108 bool m_isRectBased;
 109 ListHashSet<RefPtr<Node> > m_rectBasedTestResult;
88110};
89111
 112inline IntRect HitTestResult::rectFromPoint(int x, int y) const
 113{
 114 return rectFromPoint(IntPoint(x, y));
 115}
 116
 117// Formula:
 118// x = p.x() - padding.width()
 119// y = p.y() - padding.height()
 120// width = 2 * padding.width() + 1
 121// height = 2 * m_padding.height() + 1
 122inline IntRect HitTestResult::rectFromPoint(const IntPoint& point) const
 123{
 124 IntPoint realPoint(point);
 125 IntSize realPadding(m_padding);
 126
 127 // Real IntPoint for the rect.
 128 realPadding.clampNegativeToZero();
 129 realPoint -= realPadding;
 130
 131 // Real IntSize for the rect.
 132 realPadding.scale(2);
 133 realPadding += IntSize(1, 1);
 134
 135 return IntRect(realPoint, realPadding);
 136}
 137
90138String displayString(const String&, const Node*);
91139
92140} // namespace WebCore

WebCore/rendering/InlineFlowBox.cpp

@@bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
611611{
612612 IntRect overflowRect(visibleOverflowRect());
613613 overflowRect.move(tx, ty);
614  if (!overflowRect.contains(x, y))
 614 if (!overflowRect.intersects(result.rectFromPoint(x, y)))
615615 return false;
616616
617617 // Check children first.

@@bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
624624
625625 // Now check ourselves.
626626 IntRect rect(tx + m_x, ty + m_y, m_width, height());
627  if (visibleToHitTesting() && rect.contains(x, y)) {
 627 if (visibleToHitTesting() && rect.intersects(result.rectFromPoint(x, y))) {
628628 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.
629  return true;
 629 if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, rect))
 630 return true;
630631 }
631632
632633 return false;

WebCore/rendering/InlineTextBox.cpp

@@bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in
287287 return false;
288288
289289 IntRect rect(tx + m_x, ty + m_y, m_width, height());
290  if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.contains(x, y)) {
 290 if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.intersects(result.rectFromPoint(x, y))) {
291291 renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
292  return true;
 292 if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, rect))
 293 return true;
293294 }
294295 return false;
295296}

WebCore/rendering/RenderBlock.cpp

@@bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
37523752 // Check if we need to do anything at all.
37533753 IntRect overflowBox = visibleOverflowRect();
37543754 overflowBox.move(tx, ty);
3755  if (!overflowBox.contains(_x, _y))
 3755 if (!overflowBox.intersects(result.rectFromPoint(_x, _y)))
37563756 return false;
37573757 }
37583758
37593759 if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) {
37603760 updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3761  return true;
 3761 // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
 3762 if (!result.addNodeToRectBasedTestResult(node(), _x, _y))
 3763 return true;
37623764 }
37633765
37643766 // If we have clipping, then we can't have any spillout.
37653767 bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
37663768 bool useClip = (hasControlClip() || useOverflowClip);
3767  bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y));
 3769 IntRect hitTestArea(result.rectFromPoint(_x, _y));
 3770 bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).intersects(hitTestArea) : overflowClipRect(tx, ty).intersects(hitTestArea));
37683771 if (checkChildren) {
37693772 // Hit test descendants first.
37703773 int scrolledX = tx;

@@bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
38123815 // Now hit test our background
38133816 if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
38143817 IntRect boundsRect(tx, ty, width(), height());
3815  if (visibleToHitTesting() && boundsRect.contains(_x, _y)) {
 3818 if (visibleToHitTesting() && boundsRect.intersects(result.rectFromPoint(_x, _y))) {
38163819 updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3817  return true;
 3820 if (!result.addNodeToRectBasedTestResult(node(), _x, _y, boundsRect))
 3821 return true;
38183822 }
38193823 }
38203824

@@bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r
38393843 currYOffset += colRect.height();
38403844 colRect.move(tx, ty);
38413845
3842  if (colRect.contains(x, y)) {
 3846 if (colRect.intersects(result.rectFromPoint(x, y))) {
38433847 // The point is inside this column.
38443848 // Adjust tx and ty to change where we hit test.
38453849
38463850 int finalX = tx + currXOffset;
38473851 int finalY = ty + currYOffset;
3848  return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
 3852 if (result.isRectBasedTest() && !colRect.contains(result.rectFromPoint(x, y)))
 3853 hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
 3854 else
 3855 return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
38493856 }
38503857 }
38513858

WebCore/rendering/RenderBox.cpp

3131#include "Document.h"
3232#include "FrameView.h"
3333#include "GraphicsContext.h"
 34#include "HitTestResult.h"
3435#include "htmlediting.h"
3536#include "HTMLElement.h"
3637#include "HTMLNames.h"

@@bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
554555
555556 // Check our bounds next. For this purpose always assume that we can only be hit in the
556557 // foreground phase (which is true for replaced elements like images).
557  if (visibleToHitTesting() && action == HitTestForeground && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) {
 558 IntRect boundsRect = IntRect(tx, ty, width(), height());
 559 if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectFromPoint(xPos, yPos))) {
558560 updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
559  return true;
 561 if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect))
 562 return true;
560563 }
561564
562565 return false;

WebCore/rendering/RenderImage.cpp

@@HTMLMapElement* RenderImage::imageMap() const
377377
378378bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
379379{
380  HitTestResult tempResult(result.point());
 380 HitTestResult tempResult(result.point(), result.padding());
381381 bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction);
382382
383  if (inside && node()) {
 383 if (tempResult.innerNode() && node()) {
384384 if (HTMLMapElement* map = imageMap()) {
385385 IntRect contentBox = contentBoxRect();
386386 float zoom = style()->effectiveZoom();

@@bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
391391 }
392392 }
393393
 394 if (!inside && result.isRectBasedTest())
 395 result.append(tempResult);
394396 if (inside)
395397 result = tempResult;
396398 return inside;

WebCore/rendering/RenderLayer.cpp

@@RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
27392739#if USE(ACCELERATED_COMPOSITING)
27402740 useTemporaryClipRects = compositor()->inCompositingMode();
27412741#endif
2742 
 2742
 2743 IntRect hitTestArea = result.rectFromPoint(hitTestPoint);
 2744
27432745 // Apply a transform if we have one.
27442746 if (transform() && !appliedTransform) {
27452747 // Make sure the parent's clip rects have been calculated.
27462748 if (parent()) {
27472749 IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects);
27482750 // Go ahead and test the enclosing clip now.
2749  if (!clipRect.contains(hitTestPoint))
 2751 if (!clipRect.intersects(hitTestArea))
27502752 return 0;
27512753 }
27522754

@@RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
28592861 }
28602862
28612863 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
2862  if (fgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
 2864 if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
28632865 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
2864  HitTestResult tempResult(result.point());
 2866 HitTestResult tempResult(result.point(), result.padding());
28652867 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
28662868 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2867  result = tempResult;
 2869 if (result.isRectBasedTest())
 2870 result.append(tempResult);
 2871 else
 2872 result = tempResult;
28682873 if (!depthSortDescendants)
28692874 return this;
28702875 // Foreground can depth-sort with descendant layers, so keep this as a candidate.
28712876 candidateLayer = this;
2872  }
 2877 } else if (result.isRectBasedTest())
 2878 result.append(tempResult);
28732879 }
28742880
28752881 // Now check our negative z-index children.

@@RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
28852891 if (candidateLayer)
28862892 return candidateLayer;
28872893
2888  if (bgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
2889  HitTestResult tempResult(result.point());
 2894 if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
 2895 HitTestResult tempResult(result.point(), result.padding());
28902896 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
28912897 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2892  result = tempResult;
 2898 if (result.isRectBasedTest())
 2899 result.append(tempResult);
 2900 else
 2901 result = tempResult;
28932902 return this;
2894  }
 2903 } else if (result.isRectBasedTest())
 2904 result.append(tempResult);
28952905 }
28962906
28972907 return 0;

@@bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult&
29032913 layerBounds.x() - renderBoxX(),
29042914 layerBounds.y() - renderBoxY(),
29052915 hitTestFilter)) {
2906  // It's wrong to set innerNode, but then claim that you didn't hit anything.
2907  ASSERT(!result.innerNode());
 2916 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
 2917 // a rect-based test.
 2918 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
29082919 return false;
29092920 }
29102921

@@RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r
29382949 for (int i = list->size() - 1; i >= 0; --i) {
29392950 RenderLayer* childLayer = list->at(i);
29402951 RenderLayer* hitLayer = 0;
2941  HitTestResult tempResult(result.point());
 2952 HitTestResult tempResult(result.point(), result.padding());
29422953 if (childLayer->isPaginated())
29432954 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
29442955 else
29452956 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
 2957
 2958 // If it a rect-based test, we can safely append the temporary result since it might had hit
 2959 // nodes but not necesserily had hitLayer set.
 2960 if (result.isRectBasedTest())
 2961 result.append(tempResult);
 2962
29462963 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
29472964 resultLayer = hitLayer;
2948  result = tempResult;
 2965 if (!result.isRectBasedTest())
 2966 result = tempResult;
29492967 if (!depthSortDescendants)
29502968 break;
29512969 }

@@RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
30053023 IntRect localClipRect(hitTestRect);
30063024 localClipRect.intersect(colRect);
30073025
3008  if (!localClipRect.isEmpty() && localClipRect.contains(hitTestPoint)) {
 3026 if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectFromPoint(hitTestPoint))) {
30093027 RenderLayer* hitLayer = 0;
30103028 if (!columnIndex) {
30113029 // Apply a translation transform to change where the layer paints.

WebCore/rendering/RenderLineBoxList.cpp

2929#include "config.h"
3030#include "RenderLineBoxList.h"
3131
 32#include "HitTestResult.h"
3233#include "InlineTextBox.h"
3334#include "RenderArena.h"
3435#include "RenderInline.h"

@@bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq
245246 // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
246247 // FIXME: This check is flawed in the following extremely obscure way:
247248 // if some line in the middle has a huge overflow, it might actually extend below the last line.
248  if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow()))
 249 if (y - result.paddingHeight() >= ty + lastLineBox()->root()->bottomVisibleOverflow()
 250 || y + result.paddingHeight() < ty + firstLineBox()->root()->topVisibleOverflow())
249251 return false;
250252
251253 // See if our root lines contain the point. If so, then we hit test
252254 // them further. Note that boxes can easily overlap, so we can't make any assumptions
253255 // based off positions of our first line box or our last line box.
254256 for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) {
255  if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) {
 257 if (y + result.paddingHeight() >= ty + curr->root()->topVisibleOverflow()
 258 && y - result.paddingHeight() < ty + curr->root()->bottomVisibleOverflow()) {
256259 bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
257260 if (inside) {
258261 renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty));

WebCore/rendering/RenderSVGRoot.cpp

2626#include "RenderSVGRoot.h"
2727
2828#include "GraphicsContext.h"
 29#include "HitTestResult.h"
2930#include "RenderSVGContainer.h"
3031#include "RenderSVGResource.h"
3132#include "RenderView.h"

@@bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
319320 if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
320321 // FIXME: CSS/HTML assumes the local point is relative to the border box, right?
321322 updateHitTestResult(result, pointInBorderBox);
 323 // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet.
 324 result.addNodeToRectBasedTestResult(child->node(), _x, _y);
322325 return true;
323326 }
324327 }

WebCore/rendering/RenderTable.cpp

3131#include "Document.h"
3232#include "FixedTableLayout.h"
3333#include "FrameView.h"
 34#include "HitTestResult.h"
3435#include "HTMLNames.h"
3536#include "RenderLayer.h"
3637#include "RenderTableCell.h"

@@bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
11351136 ty += y();
11361137
11371138 // Check kids first.
1138  if (!hasOverflowClip() || overflowClipRect(tx, ty).contains(xPos, yPos)) {
 1139 if (!hasOverflowClip() || overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos))) {
11391140 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
11401141 if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) &&
11411142 child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {

@@bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
11461147 }
11471148
11481149 // Check our bounds next.
1149  if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) {
 1150 IntRect boundsRect = IntRect(tx, ty, width(), height());
 1151 if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectFromPoint(xPos, yPos))) {
11501152 updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
1151  return true;
 1153 if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect))
 1154 return true;
11521155 }
11531156
11541157 return false;

WebCore/rendering/RenderTableSection.cpp

2828
2929#include "CachedImage.h"
3030#include "Document.h"
 31#include "HitTestResult.h"
3132#include "HTMLNames.h"
3233#include "RenderTableCell.h"
3334#include "RenderTableCol.h"

@@bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
11521153 tx += x();
11531154 ty += y();
11541155
1155  if (hasOverflowClip() && !overflowClipRect(tx, ty).contains(xPos, yPos))
 1156 if (hasOverflowClip() && !overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos)))
11561157 return false;
11571158
11581159 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {

WebCore/rendering/RenderWidget.cpp

@@bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res
394394 bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action);
395395
396396 // Check to see if we are really over the widget itself (and not just in the border/padding area).
397  if (inside && !hadResult && result.innerNode() == node())
 397 if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node())
398398 result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
399399 return inside;
400400}