bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (request.allowsChildFrameContent() && widget() && widget()->isFrameView() && toFrameView(widget())->renderView()) { FrameView* childFrameView = toFrameView(widget()); RenderView* childRoot = childFrameView->renderView(); LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - childFrameView->scrollOffset(); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestLocation); bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult); if (newHitTestLocation.isRectBasedTest()) result.append(childFrameResult); else if (isInsideChildFrame) result = childFrameResult; if (isInsideChildFrame) return true; } bool hadResult = result.innerNode(); bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); // Check to see if we are really over the widget itself (and not just in the border/padding area). if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == &frameOwnerElement()) result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); return inside; }
bool LayoutTextControlSingleLine::nodeAtPoint( HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { if (!LayoutTextControl::nodeAtPoint(result, locationInContainer, accumulatedOffset, hitTestAction)) return false; // Say that we hit the inner text element if // - we hit a node inside the inner text element, // - we hit the <input> element (e.g. we're over the border or padding), or // - we hit regions not in any decoration buttons. Element* container = containerElement(); if (result.innerNode()->isDescendantOf(innerEditorElement()) || result.innerNode() == node() || (container && container == result.innerNode())) { LayoutPoint pointInParent = locationInContainer.point(); if (container && editingViewPortElement()) { if (editingViewPortElement()->layoutBox()) pointInParent -= toLayoutSize(editingViewPortElement()->layoutBox()->location()); if (container->layoutBox()) pointInParent -= toLayoutSize(container->layoutBox()->location()); } hitInnerEditorElement(result, pointInParent, accumulatedOffset); } return true; }
void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) { if (result.innerNode()) { if (result.innerNode()->document().isDNSPrefetchEnabled()) prefetchDNS(result.absoluteLinkURL().host()); } m_client->mouseDidMoveOverElement(result, modifierFlags); }
void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) { if (result.innerNode() && result.innerNode()->document().isDNSPrefetchEnabled()) prefetchDNS(result.absoluteLinkURL().host()); m_client.mouseDidMoveOverElement(result, modifierFlags); InspectorInstrumentation::mouseDidMoveOverElement(&m_page, result, modifierFlags); }
void ChromeClient::mouseDidMoveOverElement(const HitTestResult& result) { if (result.innerNode() && result.innerNode()->document().isDNSPrefetchEnabled()) prefetchDNS(result.absoluteLinkURL().host()); showMouseOverURL(result); setToolTip(result); }
bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { bool hadResult = result.innerNode(); bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); // Check to see if we are really over the widget itself (and not just in the border/padding area). if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node()) result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); return inside; }
bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction)) return false; if (result.innerNode() == node() || result.innerNode() == innerTextElement()) hitInnerTextElement(result, locationInContainer.point(), accumulatedOffset); return true; }
bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; if (result.innerNode() == node() || result.innerNode() == innerTextElement()) hitInnerTextElement(result, x, y, tx, ty); return true; }
bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action) { bool hadResult = result.innerNode(); bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action); // 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())); return inside; }
void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) { if (result.innerNode()) { Document* document = result.innerNode()->document(); if (document && document->isDNSPrefetchEnabled()) ResourceHandle::prepareForURL(result.absoluteLinkURL()); } m_client->mouseDidMoveOverElement(result, modifierFlags); InspectorInstrumentation::mouseDidMoveOverElement(m_page, result, modifierFlags); }
Document* LocalFrame::documentAtPoint(const IntPoint& point) { if (!view()) return 0; IntPoint pt = view()->windowToContents(point); HitTestResult result = HitTestResult(pt); if (contentRenderer()) result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); return result.innerNode() ? &result.innerNode()->document() : 0; }
static Document* documentAtPoint(Frame* frame, const IntPoint& point) { if (!frame || !frame->view()) return 0; IntPoint pt = frame->view()->windowToContents(point); HitTestResult result = HitTestResult(pt); if (frame->renderer()) result = frame->eventHandler()->hitTestResultAtPoint(pt, false); return result.innerNode() ? result.innerNode()->document() : 0; }
Document* Frame::documentAtPoint(const IntPoint& point) { if (!view()) return 0; LayoutPoint pt = view()->windowToContents(point); HitTestResult result = HitTestResult(pt); if (contentRenderer()) result = eventHandler()->hitTestResultAtPoint(pt, false); return result.innerNode() ? result.innerNode()->document() : 0; }
Document* LocalFrame::documentAtPoint(const IntPoint& pointInRootFrame) { if (!view()) return nullptr; IntPoint pt = view()->rootFrameToContents(pointInRootFrame); if (contentLayoutItem().isNull()) return nullptr; HitTestResult result = eventHandler().hitTestResultAtPoint( pt, HitTestRequest::ReadOnly | HitTestRequest::Active); return result.innerNode() ? &result.innerNode()->document() : nullptr; }
bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; bool resultIsTextValueOrPlaceholder = (!m_placeholderVisible && result.innerNode() == innerTextElement()) || (m_placeholderVisible && result.innerNode()->isDescendantOf(innerTextElement())); if (result.innerNode() == node() || resultIsTextValueOrPlaceholder) hitInnerTextElement(result, x, y, tx, ty); return true; }
void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) { if (result.innerNode()) { Document* document = result.innerNode()->document(); if (document && document->isDNSPrefetchEnabled()) prefetchDNS(result.absoluteLinkURL().host()); } m_client->mouseDidMoveOverElement(result, modifierFlags); #if ENABLE(INSPECTOR) if (InspectorController* inspector = m_page->inspectorController()) inspector->mouseDidMoveOverElement(result, modifierFlags); #endif }
static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest) { ASSERT(candidate.visibleNode->isElementNode()); ASSERT(candidate.visibleNode->renderer()); // Ignore iframes that don't have a src attribute if (frameOwnerElement(candidate) && (!frameOwnerElement(candidate)->contentFrame() || candidate.rect.isEmpty())) return; // Ignore off screen child nodes of containers that do not scroll (overflow:hidden) if (candidate.isOffscreen && !canBeScrolledIntoView(direction, candidate)) return; distanceDataForNode(direction, current, candidate); if (candidate.distance == maxDistance()) return; if (candidate.isOffscreenAfterScrolling && candidate.alignment < Full) return; if (closest.isNull()) { closest = candidate; return; } LayoutRect intersectionRect = intersection(candidate.rect, closest.rect); if (!intersectionRect.isEmpty() && !areElementsOnSameLine(closest, candidate)) { // If 2 nodes are intersecting, do hit test to find which node in on top. LayoutUnit x = intersectionRect.x() + intersectionRect.width() / 2; LayoutUnit y = intersectionRect.y() + intersectionRect.height() / 2; HitTestResult result = candidate.visibleNode->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true); if (candidate.visibleNode->contains(result.innerNode())) { closest = candidate; return; } if (closest.visibleNode->contains(result.innerNode())) return; } if (candidate.alignment == closest.alignment) { if (candidate.distance < closest.distance) closest = candidate; return; } if (candidate.alignment > closest.alignment) closest = candidate; }
void ChromeClient::setToolTip(LocalFrame& frame, const HitTestResult& result) { // First priority is a tooltip for element with "title" attribute. TextDirection toolTipDirection; String toolTip = result.title(toolTipDirection); // Lastly, some elements provide default tooltip strings. e.g. <input // type="file" multiple> shows a tooltip for the selected filenames. if (toolTip.isEmpty()) { if (Node* node = result.innerNode()) { if (node->isElementNode()) { toolTip = toElement(node)->defaultToolTip(); // FIXME: We should obtain text direction of tooltip from // ChromeClient or platform. As of October 2011, all client // implementations don't use text direction information for // ChromeClient::setToolTip. We'll work on tooltip text // direction during bidi cleanup in form inputs. toolTipDirection = LTR; } } } if (m_lastToolTipPoint == result.hitTestLocation().point() && m_lastToolTipText == toolTip) return; m_lastToolTipPoint = result.hitTestLocation().point(); m_lastToolTipText = toolTip; setToolTip(frame, toolTip, toolTipDirection); }
void ChromeClient::setToolTip(const HitTestResult& result) { // First priority is a potential toolTip representing a spelling or grammar // error. TextDirection toolTipDirection; String toolTip = result.spellingToolTip(toolTipDirection); // Next we'll consider a tooltip for element with "title" attribute. if (toolTip.isEmpty()) toolTip = result.title(toolTipDirection); // Lastly, for <input type="file"> that allow multiple files, we'll consider // a tooltip for the selected filenames. if (toolTip.isEmpty()) { if (Node* node = result.innerNode()) { if (isHTMLInputElement(*node)) { HTMLInputElement* input = toHTMLInputElement(node); toolTip = input->defaultToolTip(); // FIXME: We should obtain text direction of tooltip from // ChromeClient or platform. As of October 2011, all client // implementations don't use text direction information for // ChromeClient::setToolTip. We'll work on tooltip text // direction during bidi cleanup in form inputs. toolTipDirection = LTR; } } } if (m_lastToolTipPoint == result.hitTestLocation().point() && m_lastToolTipText == toolTip) return; m_lastToolTipPoint = result.hitTestLocation().point(); m_lastToolTipText = toolTip; setToolTip(toolTip, toolTipDirection); }
void AutoscrollController::updateAutoscrollLayoutObject() { if (!m_autoscrollLayoutObject) return; LayoutObject* layoutObject = m_autoscrollLayoutObject; if (RuntimeEnabledFeatures::middleClickAutoscrollEnabled()) { HitTestResult hitTest = layoutObject->frame()->eventHandler().hitTestResultAtPoint( m_middleClickAutoscrollStartPos, HitTestRequest::ReadOnly | HitTestRequest::Active); if (Node* nodeAtPoint = hitTest.innerNode()) layoutObject = nodeAtPoint->layoutObject(); } while (layoutObject && !(layoutObject->isBox() && toLayoutBox(layoutObject)->canAutoscroll())) layoutObject = layoutObject->parent(); m_autoscrollLayoutObject = layoutObject && layoutObject->isBox() ? toLayoutBox(layoutObject) : nullptr; if (m_autoscrollType != NoAutoscroll && !m_autoscrollLayoutObject) m_autoscrollType = NoAutoscroll; }
static VisiblePosition visiblePositionForHitTestResult(const HitTestResult& hitTestResult) { Node* innerNode = hitTestResult.innerNode(); VisiblePosition position(innerNode->renderer()->positionForPoint(hitTestResult.localPoint())); if (!position.isNull()) return position; return VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM); }
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction) { // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point // was on the control but not on the inner element (see Radar 4617841). // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block, // and act as if we've hit the close block if we're to the right of the inner text block. if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction)) return false; // If we hit a node inside the inner text element, say that we hit that element, // and if we hit our node (e.g. we're over the border or padding), also say that we hit the // inner text element so that it gains focus. if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node()) hitInnerTextElement(result, xPos, yPos, tx, ty); // If we're not a search field, or we already found the results or cancel buttons, we're done. if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton) return true; Node* innerNode = 0; RenderBox* innerBlockRenderer = m_innerBlock->renderBox(); RenderBox* innerTextRenderer = innerTextElement()->renderBox(); IntPoint localPoint = result.localPoint(); localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y()); int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x(); if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft) innerNode = m_resultsButton.get(); if (!innerNode) { int textRight = textLeft + innerTextRenderer->width(); if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight) innerNode = m_cancelButton.get(); } if (innerNode) { result.setInnerNode(innerNode); localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y()); } result.setLocalPoint(localPoint); return true; }
void HitTestResult::append(const HitTestResult& other) { ASSERT(isRectBasedTest() && other.isRectBasedTest()); 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 ListHashSet<RefPtr<Node> >& list = other.rectBasedTestResult(); ListHashSet<RefPtr<Node> >::const_iterator last = list.end(); for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) m_rectBasedTestResult.add(it->get()); }
void HitTestResult::append(const HitTestResult& other) { ASSERT(isRectBasedTest() && other.isRectBasedTest()); if (!m_innerNode && other.innerNode()) { m_innerNode = other.innerNode(); m_innerPossiblyPseudoNode = other.innerPossiblyPseudoNode(); m_innerNonSharedNode = other.innerNonSharedNode(); m_localPoint = other.localPoint(); m_pointInInnerNodeFrame = other.m_pointInInnerNodeFrame; } if (other.m_rectBasedTestResult) { NodeSet& set = mutableRectBasedTestResult(); for (NodeSet::const_iterator it = other.m_rectBasedTestResult->begin(), last = other.m_rectBasedTestResult->end(); it != last; ++it) set.add(it->get()); } }
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction) { // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point // was on the control but not on the inner element (see Radar 4617841). // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block, // and act as if we've hit the close block if we're to the right of the inner text block. if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction)) return false; if (result.innerNode() != element() && result.innerNode() != m_innerBlock.get()) return false; hitInnerTextBlock(result, xPos, yPos, tx, ty); if (!m_innerBlock) return true; Node* innerNode = 0; RenderBox* innerBlockRenderer = m_innerBlock->renderBox(); RenderBox* innerTextRenderer = innerTextElement()->renderBox(); IntPoint localPoint = result.localPoint(); localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y()); int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x(); if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft) innerNode = m_resultsButton.get(); if (!innerNode) { int textRight = textLeft + innerTextRenderer->width(); if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight) innerNode = m_cancelButton.get(); } if (innerNode) { result.setInnerNode(innerNode); localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y()); } result.setLocalPoint(localPoint); return true; }
void HitTestResult::append(const HitTestResult& other) { ASSERT(isRectBasedTest() && other.isRectBasedTest()); 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(); } if (other.m_rectBasedTestResult) { NodeSet& set = mutableRectBasedTestResult(); for (NodeSet::const_iterator it = other.m_rectBasedTestResult->begin(), last = other.m_rectBasedTestResult->end(); it != last; ++it) set.add(it->get()); } }
HitTestResult::HitTestResult(const HitTestResult& other) : m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_point(other.point()) , m_localPoint(other.localPoint()) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) { }
bool RenderMultiColumnFlowThread::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { // You cannot be inside an in-flow RenderFlowThread without a corresponding DOM node. It's better to // just let the ancestor figure out where we are instead. if (hitTestAction == HitTestBlockBackground) return false; bool inside = RenderFlowThread::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction); if (inside && !result.innerNode()) return false; return inside; }
bool HitTestResult::equalForCacheability(const HitTestResult& other) const { return m_hitTestRequest.equalForCacheability(other.m_hitTestRequest) && m_innerNode == other.innerNode() && m_innerPossiblyPseudoNode == other.innerPossiblyPseudoNode() && m_pointInInnerNodeFrame == other.m_pointInInnerNodeFrame && m_localPoint == other.localPoint() && m_innerURLElement == other.URLElement() && m_scrollbar == other.scrollbar() && m_isOverWidget == other.isOverWidget(); }
HitTestResult::HitTestResult(const HitTestResult& other) : m_hitTestLocation(other.m_hitTestLocation) , m_innerNode(other.innerNode()) , m_innerPossiblyPseudoNode(other.m_innerPossiblyPseudoNode) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_pointInInnerNodeFrame(other.m_pointInInnerNodeFrame) , m_localPoint(other.localPoint()) { // Only copy the NodeSet in case of rect hit test. m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0); }