// Hit Testing bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!isValid()) return false; LayoutPoint adjustedLocation = accumulatedOffset + location(); // 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). LayoutRect boundsRect = borderBoxRectInRegion(result.region()); boundsRect.moveBy(adjustedLocation); if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectForPoint(pointInContainer))) { // Check the contents of the RenderFlowThread. if (m_flowThread && m_flowThread->hitTestRegion(this, request, result, pointInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop()))) return true; updateHitTestResult(result, pointInContainer - toLayoutSize(adjustedLocation)); if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect)) return true; } return false; }
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { if (!RenderTextControl::nodeAtPoint(request, 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. HTMLElement* container = containerElement(); if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == &inputElement() || (container && container == result.innerNode())) { LayoutPoint pointInParent = locationInContainer.point(); if (container && innerBlockElement()) { if (innerBlockElement()->renderBox()) pointInParent -= toLayoutSize(innerBlockElement()->renderBox()->location()); if (container->renderBox()) pointInParent -= toLayoutSize(container->renderBox()->location()); } hitInnerTextElement(result, pointInParent, accumulatedOffset); } return true; }
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction); if (tempResult.innerNode() && node()) { if (HTMLMapElement* map = imageMap()) { IntRect contentBox = contentBoxRect(); float zoom = style()->effectiveZoom(); int mapX = lroundf((x - tx - this->x() - contentBox.x()) / zoom); int mapY = lroundf((y - ty - this->y() - contentBox.y()) / zoom); if (map->mapMouseEvent(mapX, mapY, contentBox.size(), tempResult)) tempResult.setInnerNonSharedNode(node()); } } if (!inside && result.isRectBasedTest()) result.append(tempResult); if (inside) result = tempResult; return inside; }
bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { if (!RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; const Vector<Element*>& listItems = toSelectElement(static_cast<Element*>(node()))->listItems(); int size = numItems(); tx += this->x(); ty += this->y(); for (int i = 0; i < size; ++i) { if (itemBoundingBoxRect(tx, ty, i).contains(x, y)) { if (Element* node = listItems[i]) { result.setInnerNode(node); if (!result.innerNonSharedNode()) result.setInnerNonSharedNode(node); result.setLocalPoint(IntPoint(x - tx, y - ty)); break; } } } return true; }
void NewEventHandler::updateSelectionForPointerDown(const HitTestResult& hitTestResult, const WebPointerEvent& event) { Node* innerNode = hitTestResult.innerNode(); if (!innerNode || !innerNode->renderer()) return; if (Position::nodeIsUserSelectNone(innerNode)) return; if (!innerNode->dispatchEvent(Event::createCancelableBubble(EventTypeNames::selectstart))) return; VisiblePosition position = visiblePositionForHitTestResult(hitTestResult); // TODO(abarth): Can we change this to setSelectionIfNeeded? m_frame.selection().setNonDirectionalSelectionIfNeeded(VisibleSelection(position), CharacterGranularity); }
void Chrome::setToolTip(const HitTestResult& result) { // First priority is a potential toolTip representing a spelling or grammar error TextDirection toolTipDirection; String toolTip = result.spellingToolTip(toolTipDirection); // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those). if (toolTip.isEmpty() && m_page.settings().showsURLsInToolTips()) { if (Element* element = result.innerNonSharedElement()) { // Get tooltip representing form action, if relevant if (isHTMLInputElement(element)) { HTMLInputElement* input = toHTMLInputElement(element); if (input->isSubmitButton()) { if (HTMLFormElement* form = input->form()) { toolTip = form->action(); if (form->renderer()) toolTipDirection = form->renderer()->style()->direction(); else toolTipDirection = LTR; } } } } // Get tooltip representing link's URL if (toolTip.isEmpty()) { // FIXME: Need to pass this URL through userVisibleString once that's in WebCore toolTip = result.absoluteLinkURL().string(); // URL always display as LTR. toolTipDirection = LTR; } } // Next we'll consider a tooltip for element with "title" attribute if (toolTip.isEmpty()) toolTip = result.title(toolTipDirection); if (toolTip.isEmpty() && m_page.settings().showsToolTipOverTruncatedText()) toolTip = result.innerTextIfTruncated(toolTipDirection); // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames if (toolTip.isEmpty()) { if (Element* element = result.innerNonSharedElement()) { if (isHTMLInputElement(element)) { toolTip = toHTMLInputElement(element)->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; } } } m_client.setToolTip(toolTip, toolTipDirection); }
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { HitTestResult tempResult(result.hitTestLocation()); bool inside = RenderReplaced::nodeAtPoint(request, tempResult, locationInContainer, accumulatedOffset, hitTestAction); if (tempResult.innerNode() && node()) { if (HTMLMapElement* map = imageMap()) { LayoutRect contentBox = contentBoxRect(); float scaleFactor = 1 / style()->effectiveZoom(); LayoutPoint mapLocation = locationInContainer.point() - toLayoutSize(accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location()); mapLocation.scale(scaleFactor, scaleFactor); if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult)) tempResult.setInnerNonSharedNode(node()); } } if (!inside && result.isRectBasedTest()) result.append(tempResult); if (inside) result = tempResult; return inside; }
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding()); bool inside = RenderReplaced::nodeAtPoint(request, tempResult, pointInContainer, accumulatedOffset, hitTestAction); if (tempResult.innerNode() && node()) { if (HTMLMapElement* map = imageMap()) { IntRect contentBox = contentBoxRect(); float scaleFactor = 1 / style()->effectiveZoom(); LayoutPoint mapLocation(pointInContainer.x() - accumulatedOffset.x() - this->x() - contentBox.x(), pointInContainer.y() - accumulatedOffset.y() - this->y() - contentBox.y()); mapLocation.scale(scaleFactor, scaleFactor); if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult)) tempResult.setInnerNonSharedNode(node()); } } if (!inside && result.isRectBasedTest()) result.append(tempResult); if (inside) result = tempResult; return inside; }
bool InlineTextBox::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) { if (isLineBreak() || m_truncation == cFullTruncation) return false; LayoutPoint boxOrigin = physicalLocation(); boxOrigin.moveBy(accumulatedOffset); LayoutRect rect(boxOrigin, size()); if (visibleToHitTestRequest(result.hitTestRequest()) && locationInContainer.intersects(rect)) { getLineLayoutItem().updateHitTestResult( result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); if (result.addNodeToListBasedTestResult(getLineLayoutItem().node(), locationInContainer, rect) == StopHitTesting) return true; } return false; }
bool HitTestCache::lookupCachedResult(HitTestResult& hitResult, uint64_t domTreeVersion) { bool result = false; HitHistogramMetric metric = HitHistogramMetric::MISS; if (hitResult.hitTestRequest().avoidCache()) { metric = HitHistogramMetric::MISS_EXPLICIT_AVOID; // For now we don't support rect based hit results. } else if (domTreeVersion == m_domTreeVersion && !hitResult.hitTestLocation().isRectBasedTest()) { for (const auto& cachedItem : m_items) { if (cachedItem.hitTestLocation().point() == hitResult.hitTestLocation().point()) { if (hitResult.hitTestRequest().equalForCacheability(cachedItem.hitTestRequest())) { metric = HitHistogramMetric::HIT_EXACT_MATCH; result = true; hitResult = cachedItem; break; } metric = HitHistogramMetric::MISS_VALIDITY_RECT_MATCHES; } } } Platform::current()->histogramEnumeration("Event.HitTest", static_cast<int>(metric), static_cast<int>(HitHistogramMetric::MAX_HIT_METRIC)); return result; }
bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameContent()) return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); FrameView* childFrameView = toFrameView(widget()); RenderView* childRoot = childFrameView->renderView(); if (childRoot) { 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; if (request.allowsFrameScrollbars()) { // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls, // so we need to test ScrollView scrollbars separately here. // FIXME: Consider if this test could be done unconditionally. Scrollbar* frameScrollbar = childFrameView->scrollbarAtPoint(newHitTestLocation.roundedPoint()); if (frameScrollbar) result.setScrollbar(frameScrollbar); } } return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); }
void WebPage::findZoomableAreaForPoint(const IntPoint& point, const IntSize& area) { UNUSED_PARAM(area); Frame* mainframe = m_mainFrame->coreFrame(); HitTestResult result = mainframe->eventHandler().hitTestResultAtPoint(mainframe->view()->windowToContents(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); Node* node = result.innerNode(); if (!node) return; IntRect zoomableArea = node->pixelSnappedBoundingBox(); while (true) { bool found = !node->isTextNode() && !node->isShadowRoot(); // No candidate found, bail out. if (!found && !node->parentNode()) return; // Candidate found, and it is a better candidate than its parent. // NB: A parent is considered a better candidate iff the node is // contained by it and it is the only child. if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1)) break; node = node->parentNode(); zoomableArea.unite(node->pixelSnappedBoundingBox()); } if (node->document().frame() && node->document().frame()->view()) { const ScrollView* view = node->document().frame()->view(); zoomableArea = view->contentsToWindow(zoomableArea); } send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea)); }
// Helper function to get misspelled word on which context menu // is to be evolked. This function also sets the word on which context menu // has been evoked to be the selected word, as required. This function changes // the selection only when there were no selected characters on OS X. static String selectMisspelledWord(const ContextMenu* defaultMenu, Frame* selectedFrame) { // First select from selectedText to check for multiple word selection. String misspelledWord = selectedFrame->editor()->selectedText().stripWhiteSpace(); // If some texts were already selected, we don't change the selection. if (!misspelledWord.isEmpty()) { // Don't provide suggestions for multiple words. if (!isASingleWord(misspelledWord)) return String(); return misspelledWord; } // Selection is empty, so change the selection to the word under the cursor. HitTestResult hitTestResult = selectedFrame->eventHandler()-> hitTestResultAtPoint(defaultMenu->hitTestResult().point(), true); Node* innerNode = hitTestResult.innerNode(); VisiblePosition pos(innerNode->renderer()->positionForPoint( hitTestResult.localPoint())); if (pos.isNull()) return misspelledWord; // It is empty. WebFrameImpl::selectWordAroundPosition(selectedFrame, pos); misspelledWord = selectedFrame->editor()->selectedText().stripWhiteSpace(); #if OS(DARWIN) // If misspelled word is still empty, then that portion should not be // selected. Set the selection to that position only, and do not expand. if (misspelledWord.isEmpty()) selectedFrame->selection()->setSelection(VisibleSelection(pos)); #else // On non-Mac, right-click should not make a range selection in any case. selectedFrame->selection()->setSelection(VisibleSelection(pos)); #endif return misspelledWord; }
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()) { // Only copy the padding and ListHashSet in case of rect hit test. // Copying the later is rather expensive. if ((m_isRectBased = other.isRectBasedTest())) { m_topPadding = other.m_topPadding; m_rightPadding = other.m_rightPadding; m_bottomPadding = other.m_bottomPadding; m_leftPadding = other.m_leftPadding; m_rectBasedTestResult = other.rectBasedTestResult(); } else m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0; }
bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) { if (isLineBreak()) return false; FloatPoint boxOrigin = locationIncludingFlipping(); boxOrigin.moveBy(accumulatedOffset); FloatRect rect(boxOrigin, size()); if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) { renderer().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect)) return true; } return false; }
void HitTestResult::append(const HitTestResult& other) { ASSERT(isRectBasedTest() && other.isRectBasedTest()); if (!m_scrollbar && other.scrollbar()) { setScrollbar(other.scrollbar()); } 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; m_innerURLElement = other.URLElement(); 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()); } }
PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y) { if (!renderView()) return nullptr; HitTestResult result = hitTestInDocument(this, x, y); RenderObject* renderer = result.renderer(); if (!renderer) return nullptr; Node* node = renderer->node(); Node* shadowAncestorNode = ancestorInThisScope(node); if (shadowAncestorNode != node) { unsigned offset = shadowAncestorNode->nodeIndex(); ContainerNode* container = shadowAncestorNode->parentNode(); return Range::create(*this, container, offset, container, offset); } PositionWithAffinity positionWithAffinity = result.position(); if (positionWithAffinity.position().isNull()) return nullptr; Position rangeCompliantPosition = positionWithAffinity.position().parentAnchoredEquivalent(); return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition); }
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) { LayoutPoint pointInParent = locationInContainer.point() - toLayoutSize(accumulatedOffset); LayoutPoint pointInBorderBox = pointInParent - toLayoutSize(location()); // Only test SVG content if the point is in our content box. // FIXME: This should be an intersection when rect-based hit tests are supported by nodeAtFloatPoint. if (contentBoxRect().contains(pointInBorderBox)) { FloatPoint localPoint = localToParentTransform().inverse().mapPoint(FloatPoint(pointInParent)); for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { updateHitTestResult(result, pointInBorderBox); if (!result.addNodeToRectBasedTestResult(child->node(), request, locationInContainer)) return true; } } } // If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit. if (hitTestAction == HitTestBlockBackground && visibleToHitTesting()) { // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase, // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able // to detect these hits anymore. LayoutRect boundsRect(accumulatedOffset + location(), size()); if (locationInContainer.intersects(boundsRect)) { updateHitTestResult(result, pointInBorderBox); if (!result.addNodeToRectBasedTestResult(&svgSVGElement(), request, locationInContainer, boundsRect)) return true; } } return false; }
bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty) { if (!m_vBar) return false; IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(), _ty + borderTop(), m_vBar->width(), height() - borderTop() - borderBottom()); if (vertRect.contains(_x, _y)) { result.setScrollbar(m_vBar.get()); return true; } return false; }
IntRect WebHitTestResult::Data::elementBoundingBoxInWindowCoordinates(const HitTestResult& hitTestResult) { Node* node = hitTestResult.innerNonSharedNode(); if (!node) return IntRect(); Frame* frame = node->document().frame(); if (!frame) return IntRect(); FrameView* view = frame->view(); if (!view) return IntRect(); return view->contentsToWindow(node->pixelSnappedBoundingBox()); }
void LayoutTextControl::hitInnerEditorElement( HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { HTMLElement* innerEditor = innerEditorElement(); if (!innerEditor->layoutObject()) return; LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerEditor->layoutBox()->location()); if (hasOverflowClip()) localPoint += scrolledContentOffset(); result.setNodeAndPosition(innerEditor, localPoint); }
bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { if (!m_vBar || !m_vBar->shouldParticipateInHitTesting()) return false; LayoutRect vertRect(accumulatedOffset.x() + width() - borderRight() - m_vBar->width(), accumulatedOffset.y() + borderTop(), m_vBar->width(), height() - borderTop() - borderBottom()); if (vertRect.contains(pointInContainer)) { result.setScrollbar(m_vBar.get()); return true; } return false; }
bool RenderListBox::isPointInScrollbar(HitTestResult& result, int _x, int _y, int _tx, int _ty) { if (!m_vBar) return false; IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(), _ty + borderTop() - borderTopExtra(), m_vBar->width(), height() + borderTopExtra() + borderBottomExtra() - borderTop() - borderBottom()); if (vertRect.contains(_x, _y)) { result.setScrollbar(m_vBar->isWidget() ? static_cast<PlatformScrollbar*>(m_vBar.get()) : 0); return true; } return false; }
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) : HitTestLocation(other) , m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_localPoint(other.localPoint()) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) { // Only copy the NodeSet in case of rect hit test. m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0); }
void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) { if (result.absoluteLinkURL() != lastHoverURL || result.title() != lastHoverTitle || result.textContent() != lastHoverContent) { lastHoverURL = result.absoluteLinkURL(); lastHoverTitle = result.title(); lastHoverContent = result.textContent(); emit m_webPage->linkHovered(lastHoverURL.prettyURL(), lastHoverTitle, lastHoverContent); } }
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) { bool inside = RenderReplaced::nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction); if (inside && element()) { int tx = _tx + m_x; int ty = _ty + m_y; HTMLMapElement* map = imageMap(); if (map) { // we're a client side image map inside = map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), result); result.setInnerNonSharedNode(element()); } } return inside; }
bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result) { if (layer()->hitTest(request, location, result)) return true; // FIXME: Consider if this test should be done unconditionally. if (request.allowsFrameScrollbars()) { // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls, // so we need to test ScrollView scrollbars separately here. Scrollbar* frameScrollbar = frameView().scrollbarAtPoint(location.roundedPoint()); if (frameScrollbar) { result.setScrollbar(frameScrollbar); return true; } } return false; }
void ChromeClientQt::mouseDidMoveOverElement(const HitTestResult& result, unsigned) { TextDirection dir; if (result.absoluteLinkURL() != lastHoverURL || result.title(dir) != lastHoverTitle || result.textContent() != lastHoverContent) { lastHoverURL = result.absoluteLinkURL(); lastHoverTitle = result.title(dir); lastHoverContent = result.textContent(); emit m_webPage->linkHovered(lastHoverURL.string(), lastHoverTitle, lastHoverContent); } }
HitTestResult::HitTestResult(const HitTestResult& other) : m_hitTestLocation(other.m_hitTestLocation) , m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_pointInInnerNodeFrame(other.m_pointInInnerNodeFrame) , m_localPoint(other.localPoint()) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) { // Only copy the NodeSet in case of rect hit test. m_rectBasedTestResult = other.m_rectBasedTestResult ? std::make_unique<NodeSet>(*other.m_rectBasedTestResult) : nullptr; }