// 'region' is in contents coordinates relative to the frame containing 'node' // 'remainingFingerRegion' and 'intersectingRegions' will always be in main frame contents // coordinates. // Thus, before comparing, we need to map the former to main frame contents coordinates. bool FatFingers::checkFingerIntersection(const Platform::IntRectRegion& region, const Platform::IntRectRegion& remainingFingerRegion, Node* node, Vector<IntersectingRegion>& intersectingRegions) { ASSERT(node); Platform::IntRectRegion regionCopy(region); WebCore::IntPoint framePos(m_webPage->frameOffset(node->document()->frame())); regionCopy.move(framePos.x(), framePos.y()); Platform::IntRectRegion intersection = intersectRegions(regionCopy, remainingFingerRegion); if (intersection.isEmpty()) return false; #if DEBUG_FAT_FINGERS String nodeName; if (node->isTextNode()) nodeName = "text node"; else if (node->isElementNode()) nodeName = String::format("%s node", toElement(node)->tagName().latin1().data()); else nodeName = "unknown node"; log(LogLevelInfo, "%s has region %s, intersecting at %s (area %d)", nodeName.latin1().data(), regionCopy.toString().c_str(), intersection.toString().c_str(), intersection.area()); #endif intersectingRegions.append(std::make_pair(node, intersection)); return true; }
bool FatFingers::checkForClickableElement(Element* curElement, Vector<IntersectingRegion>& intersectingRegions, IntRectRegion& remainingFingerRegion, RenderLayer*& lowestPositionedEnclosingLayerSoFar) { ASSERT(curElement); bool intersects = false; IntRectRegion elementRegion; bool isClickableElement = isElementClickable(curElement); if (isClickableElement) { if (curElement->isLink()) { // Links can wrap lines, and in such cases Node::boundingBox() can give us // not accurate rects, since it unites all InlineBox's rects. In these // cases, we can process each line of the link separately with our // intersection rect, getting a more accurate clicking. Vector<FloatQuad> quads; curElement->renderer()->absoluteFocusRingQuads(quads); size_t n = quads.size(); ASSERT(n); for (size_t i = 0; i < n; ++i) elementRegion = unionRegions(elementRegion, Platform::IntRect(quads[i].enclosingBoundingBox())); } else elementRegion = IntRectRegion(curElement->renderer()->absoluteBoundingBoxRect(true /*use transforms*/)); } else elementRegion = IntRectRegion(curElement->renderer()->absoluteBoundingBoxRect(true /*use transforms*/)); if (lowestPositionedEnclosingLayerSoFar) { RenderLayer* curElementRenderLayer = m_webPage->enclosingPositionedAncestorOrSelfIfPositioned(curElement->renderer()->enclosingLayer()); if (curElementRenderLayer != lowestPositionedEnclosingLayerSoFar) { // elementRegion will always be in contents coordinates of its container frame. It needs to be // mapped to main frame contents coordinates in order to intersect the fingerRegion, then. WebCore::IntPoint framePos(m_webPage->frameOffset(curElement->document()->frame())); IntRectRegion layerRegion(Platform::IntRect(lowestPositionedEnclosingLayerSoFar->renderer()->absoluteBoundingBoxRect(true/*use transforms*/))); layerRegion.move(framePos.x(), framePos.y()); remainingFingerRegion = intersectRegions(remainingFingerRegion, layerRegion); lowestPositionedEnclosingLayerSoFar = curElementRenderLayer; } } else lowestPositionedEnclosingLayerSoFar = m_webPage->enclosingPositionedAncestorOrSelfIfPositioned(curElement->renderer()->enclosingLayer()); if (isClickableElement) intersects = checkFingerIntersection(elementRegion, remainingFingerRegion, curElement, intersectingRegions); return intersects; }