void ChromeClientImpl::mouseDidMoveOverElement( const HitTestResult& result, unsigned modifierFlags) { if (!m_webView->client()) return; WebURL url; // Find out if the mouse is over a link, and if so, let our UI know... if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty()) url = result.absoluteLinkURL(); else if (result.innerNonSharedNode() && (result.innerNonSharedNode()->hasTagName(HTMLNames::objectTag) || result.innerNonSharedNode()->hasTagName(HTMLNames::embedTag))) { RenderObject* object = result.innerNonSharedNode()->renderer(); if (object && object->isWidget()) { Widget* widget = toRenderWidget(object)->widget(); if (widget && widget->isPluginContainer()) { WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(widget); url = plugin->plugin()->linkAtPosition(result.point()); } } } m_webView->client()->setMouseOverURL(url); }
bool RenderFlowThread::hitTestRegion(RenderRegion* region, const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { LayoutRect regionRect(region->regionRect()); LayoutRect regionOverflowRect = region->regionOverflowRect(); LayoutRect regionClippingRect(accumulatedOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size()); if (!regionClippingRect.contains(pointInContainer)) return false; LayoutPoint renderFlowThreadOffset; if (style()->isFlippedBlocksWritingMode()) { LayoutRect flippedRegionRect(regionRect); flipForWritingMode(flippedRegionRect); renderFlowThreadOffset = LayoutPoint(accumulatedOffset - flippedRegionRect.location()); } else renderFlowThreadOffset = LayoutPoint(accumulatedOffset - regionRect.location()); LayoutPoint transformedPoint(pointInContainer.x() - renderFlowThreadOffset.x(), pointInContainer.y() - renderFlowThreadOffset.y()); // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView. HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping); RenderRegion* oldRegion = result.region(); result.setRegion(region); LayoutPoint oldPoint = result.point(); result.setPoint(transformedPoint); bool isPointInsideFlowThread = layer()->hitTest(newRequest, result); result.setPoint(oldPoint); result.setRegion(oldRegion); // FIXME: Should we set result.m_localPoint back to the RenderRegion's coordinate space or leave it in the RenderFlowThread's coordinate // space? Right now it's staying in the RenderFlowThread's coordinate space, which may end up being ok. We will know more when we get around to // patching positionForPoint. return isPointInsideFlowThread; }
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()) { }
ContextMenu::ContextMenu(const HitTestResult& result) : m_hitTestResult(result), m_platformDescription( NULL ) { /* Get position */ if( result.innerNode() != NULL && result.innerNode()->document() != NULL ) { os::View* pcView = result.innerNode()->document()->frame()->view()->syllableWidget(); int nChild = 0; while( pcView->GetChildAt( nChild ) != NULL ) { if( pcView->GetChildAt( nChild )->GetName() == "scroll_view_canvas" ) { m_point = pcView->GetChildAt( nChild )->ConvertToScreen( os::Point( result.point().x(), result.point().y() ) ); break; } nChild++; } } DEBUG("ContextMenu::ContextMenu() %i %i\n", result.point().x(), result.point().y()); m_platformDescription = new os::Menu( os::Rect(), "", os::ITEMS_IN_COLUMN ); }
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) { HitTestResult tempResult(result.point()); bool inside = RenderReplaced::nodeAtPoint(request, tempResult, _x, _y, _tx, _ty, hitTestAction); if (inside && node()) { int tx = _tx + x(); int ty = _ty + y(); if (HTMLMapElement* map = imageMap()) { if (map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), tempResult)) tempResult.setInnerNonSharedNode(node()); } } if (inside) result = tempResult; return inside; }
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 RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) { HitTestResult tempResult(result.point()); bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction); if (inside && 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 = 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; }
PlatformMenuDescription ContextMenuClientImpl::getCustomMenuFromDefaultItems( ContextMenu* defaultMenu) { // Displaying the context menu in this function is a big hack as we don't // have context, i.e. whether this is being invoked via a script or in // response to user input (Mouse event WM_RBUTTONDOWN, // Keyboard events KeyVK_APPS, Shift+F10). Check if this is being invoked // in response to the above input events before popping up the context menu. if (!m_webView->contextMenuAllowed()) return 0; HitTestResult r = defaultMenu->hitTestResult(); Frame* selectedFrame = r.innerNonSharedNode()->document()->frame(); WebContextMenuData data; data.mousePosition = selectedFrame->view()->contentsToWindow(r.point()); // Compute edit flags. data.editFlags = WebContextMenuData::CanDoNone; if (m_webView->focusedWebCoreFrame()->editor()->canUndo()) data.editFlags |= WebContextMenuData::CanUndo; if (m_webView->focusedWebCoreFrame()->editor()->canRedo()) data.editFlags |= WebContextMenuData::CanRedo; if (m_webView->focusedWebCoreFrame()->editor()->canCut()) data.editFlags |= WebContextMenuData::CanCut; if (m_webView->focusedWebCoreFrame()->editor()->canCopy()) data.editFlags |= WebContextMenuData::CanCopy; if (m_webView->focusedWebCoreFrame()->editor()->canPaste()) data.editFlags |= WebContextMenuData::CanPaste; if (m_webView->focusedWebCoreFrame()->editor()->canDelete()) data.editFlags |= WebContextMenuData::CanDelete; // We can always select all... data.editFlags |= WebContextMenuData::CanSelectAll; data.editFlags |= WebContextMenuData::CanTranslate; // Links, Images, Media tags, and Image/Media-Links take preference over // all else. data.linkURL = r.absoluteLinkURL(); if (!r.absoluteImageURL().isEmpty()) { data.srcURL = r.absoluteImageURL(); data.mediaType = WebContextMenuData::MediaTypeImage; } else if (!r.absoluteMediaURL().isEmpty()) { data.srcURL = r.absoluteMediaURL(); // We know that if absoluteMediaURL() is not empty, then this // is a media element. HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(r.innerNonSharedNode()); if (mediaElement->hasTagName(HTMLNames::videoTag)) data.mediaType = WebContextMenuData::MediaTypeVideo; else if (mediaElement->hasTagName(HTMLNames::audioTag)) data.mediaType = WebContextMenuData::MediaTypeAudio; if (mediaElement->error()) data.mediaFlags |= WebContextMenuData::MediaInError; if (mediaElement->paused()) data.mediaFlags |= WebContextMenuData::MediaPaused; if (mediaElement->muted()) data.mediaFlags |= WebContextMenuData::MediaMuted; if (mediaElement->loop()) data.mediaFlags |= WebContextMenuData::MediaLoop; if (mediaElement->supportsSave()) data.mediaFlags |= WebContextMenuData::MediaCanSave; if (mediaElement->hasAudio()) data.mediaFlags |= WebContextMenuData::MediaHasAudio; if (mediaElement->hasVideo()) data.mediaFlags |= WebContextMenuData::MediaHasVideo; if (mediaElement->controls()) data.mediaFlags |= WebContextMenuData::MediaControls; } else if (r.innerNonSharedNode()->hasTagName(HTMLNames::objectTag) || r.innerNonSharedNode()->hasTagName(HTMLNames::embedTag)) { RenderObject* object = r.innerNonSharedNode()->renderer(); if (object && object->isWidget()) { Widget* widget = toRenderWidget(object)->widget(); if (widget && widget->isPluginContainer()) { WebPluginContainerImpl* plugin = static_cast<WebPluginContainerImpl*>(widget); WebString text = plugin->plugin()->selectionAsText(); if (!text.isEmpty()) { data.selectedText = text; data.editFlags |= WebContextMenuData::CanCopy; } data.editFlags &= ~WebContextMenuData::CanTranslate; data.linkURL = plugin->plugin()->linkAtPosition(data.mousePosition); } } } data.isImageBlocked = (data.mediaType == WebContextMenuData::MediaTypeImage) && !r.image(); // If it's not a link, an image, a media element, or an image/media link, // show a selection menu or a more generic page menu. data.frameEncoding = selectedFrame->loader()->writer()->encoding(); // Send the frame and page URLs in any case. data.pageURL = urlFromFrame(m_webView->mainFrameImpl()->frame()); if (selectedFrame != m_webView->mainFrameImpl()->frame()) data.frameURL = urlFromFrame(selectedFrame); if (r.isSelected()) data.selectedText = selectedFrame->editor()->selectedText().stripWhiteSpace(); if (r.isContentEditable()) { data.isEditable = true; if (m_webView->focusedWebCoreFrame()->editor()->isContinuousSpellCheckingEnabled()) { data.isSpellCheckingEnabled = true; // Spellchecking might be enabled for the field, but could be disabled on the node. if (m_webView->focusedWebCoreFrame()->editor()->spellCheckingEnabledInFocusedNode()) data.misspelledWord = selectMisspelledWord(defaultMenu, selectedFrame); } } #if OS(DARWIN) ExceptionCode ec = 0; RefPtr<CSSStyleDeclaration> style = selectedFrame->document()->createCSSStyleDeclaration(); style->setProperty(CSSPropertyDirection, "ltr", false, ec); if (selectedFrame->editor()->selectionHasStyle(style.get()) != FalseTriState) data.writingDirectionLeftToRight |= WebContextMenuData::CheckableMenuItemChecked; style->setProperty(CSSPropertyDirection, "rtl", false, ec); if (selectedFrame->editor()->selectionHasStyle(style.get()) != FalseTriState) data.writingDirectionRightToLeft |= WebContextMenuData::CheckableMenuItemChecked; #endif // OS(DARWIN) // Now retrieve the security info. DocumentLoader* dl = selectedFrame->loader()->documentLoader(); WebDataSource* ds = WebDataSourceImpl::fromDocumentLoader(dl); if (ds) data.securityInfo = ds->response().securityInfo(); // Filter out custom menu elements and add them into the data. populateCustomMenuItems(defaultMenu, &data); WebFrame* selected_web_frame = WebFrameImpl::fromFrame(selectedFrame); if (m_webView->client()) m_webView->client()->showContextMenu(selected_web_frame, data); return 0; }