void ViewportAnchor::setAnchor(const IntRect& viewRect, const FloatSize& anchorInViewCoords) { m_viewRect = viewRect; m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_anchorInViewCoords = anchorInViewCoords; if (viewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (viewRect.location() == IntPoint::zero()) return; FloatSize anchorOffset = viewRect.size(); anchorOffset.scale(anchorInViewCoords.width(), anchorInViewCoords.height()); const FloatPoint anchorPoint = FloatPoint(viewRect.location()) + anchorOffset; Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), viewRect, m_eventHandler); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPoint - m_anchorNodeBounds.location(); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e) { m_position = widget->convertFromRootFrame(flooredIntPoint(convertHitPointToRootFrame(widget, FloatPoint(e.x, e.y)))); m_globalPosition = IntPoint(e.globalX, e.globalY); m_deltaX = e.deltaX; m_deltaY = e.deltaY; m_wheelTicksX = e.wheelTicksX; m_wheelTicksY = e.wheelTicksY; m_granularity = e.scrollByPage ? ScrollByPageWheelEvent : ScrollByPixelWheelEvent; m_type = PlatformEvent::Wheel; m_timestamp = e.timeStampSeconds; m_modifiers = e.modifiers; m_hasPreciseScrollingDeltas = e.hasPreciseScrollingDeltas; m_canScroll = e.canScroll; m_resendingPluginId = e.resendingPluginId; m_railsMode = static_cast<PlatformEvent::RailsMode>(e.railsMode); #if OS(MACOSX) m_phase = static_cast<PlatformWheelEventPhase>(e.phase); m_momentumPhase = static_cast<PlatformWheelEventPhase>(e.momentumPhase); m_canRubberbandLeft = e.canRubberbandLeft; m_canRubberbandRight = e.canRubberbandRight; #endif }
IntRect enclosingIntRect(const FloatRect& rect) { IntPoint location = flooredIntPoint(rect.minXMinYCorner()); IntPoint maxPoint = ceiledIntPoint(rect.maxXMaxYCorner()); return IntRect(location, maxPoint - location); }
WebRenderObject::WebRenderObject(RenderObject* renderer) { m_name = renderer->renderName(); // FIXME: broken with transforms m_absolutePosition = flooredIntPoint(renderer->localToAbsolute(FloatPoint())); if (renderer->isBox()) m_frameRect = toRenderBox(renderer)->frameRect(); else if (renderer->isText()) { m_frameRect = toRenderText(renderer)->linesBoundingBox(); m_frameRect.setX(toRenderText(renderer)->firstRunX()); m_frameRect.setY(toRenderText(renderer)->firstRunY()); } else if (renderer->isRenderInline()) m_frameRect = toRenderBoxModelObject(renderer)->borderBoundingBox(); m_children = MutableArray::create(); for (RenderObject* coreChild = renderer->firstChild(); coreChild; coreChild = coreChild->nextSibling()) { RefPtr<WebRenderObject> child = adoptRef(new WebRenderObject(coreChild)); m_children->append(child.get()); } if (!renderer->isWidget()) return; Widget* widget = toRenderWidget(renderer)->widget(); if (!widget || !widget->isFrameView()) return; FrameView* frameView = static_cast<FrameView*>(widget); if (RenderView* coreContentRenderer = frameView->frame()->contentRenderer()) { RefPtr<WebRenderObject> contentRenderer = adoptRef(new WebRenderObject(coreContentRenderer)); m_children->append(contentRenderer.get()); } }
CCInputHandlerClient::ScrollStatus CCLayerImpl::tryScroll(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) const { if (shouldScrollOnMainThread()) { TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed shouldScrollOnMainThread"); return CCInputHandlerClient::ScrollOnMainThread; } if (!screenSpaceTransform().isInvertible()) { TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored nonInvertibleTransform"); return CCInputHandlerClient::ScrollIgnored; } if (!nonFastScrollableRegion().isEmpty()) { bool clipped = false; FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(screenSpaceTransform().inverse(), FloatPoint(viewportPoint), clipped); if (!clipped && nonFastScrollableRegion().contains(flooredIntPoint(hitTestPointInLocalSpace))) { TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed nonFastScrollableRegion"); return CCInputHandlerClient::ScrollOnMainThread; } } if (type == CCInputHandlerClient::Wheel && haveWheelEventHandlers()) { TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Failed wheelEventHandlers"); return CCInputHandlerClient::ScrollOnMainThread; } if (!scrollable()) { TRACE_EVENT0("cc", "CCLayerImpl::tryScroll: Ignored not scrollable"); return CCInputHandlerClient::ScrollIgnored; } return CCInputHandlerClient::ScrollStarted; }
void RotationViewportAnchor::computeOrigins( const FloatSize& innerSize, IntPoint& mainFrameOffset, FloatPoint& visualViewportOffset) const { IntSize outerSize = layoutViewport().visibleContentRect().size(); // Compute the viewport origins in CSS pixels relative to the document. FloatSize absVisualViewportOffset = m_normalizedVisualViewportOffset; absVisualViewportOffset.scale(outerSize.width(), outerSize.height()); FloatPoint innerOrigin = getInnerOrigin(innerSize); FloatPoint outerOrigin = innerOrigin - absVisualViewportOffset; IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize); FloatRect innerRect = FloatRect(innerOrigin, innerSize); moveToEncloseRect(outerRect, innerRect); outerRect.setLocation(IntPoint( layoutViewport().clampScrollOffset(toIntSize(outerRect.location())))); moveIntoRect(innerRect, outerRect); mainFrameOffset = outerRect.location(); visualViewportOffset = FloatPoint(innerRect.location() - outerRect.location()); }
void RotationViewportAnchor::setAnchor() { RootFrameViewport* rootFrameViewport = m_rootFrameView->getRootFrameViewport(); DCHECK(rootFrameViewport); m_oldPageScaleFactor = m_visualViewport->scale(); m_oldMinimumPageScaleFactor = m_pageScaleConstraintsSet.finalConstraints().minimumScale; // Save the absolute location in case we won't find the anchor node, we'll // fall back to that. m_visualViewportInDocument = FloatPoint(rootFrameViewport->visibleContentRect().location()); m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_normalizedVisualViewportOffset = FloatSize(); IntRect innerViewRect = rootFrameViewport->visibleContentRect(); // Preserve origins at the absolute screen origin. if (innerViewRect.location() == IntPoint::zero() || innerViewRect.isEmpty()) return; IntRect outerViewRect = layoutViewport().visibleContentRect(IncludeScrollbars); // Normalize by the size of the outer rect DCHECK(!outerViewRect.isEmpty()); m_normalizedVisualViewportOffset = m_visualViewport->getScrollOffset(); m_normalizedVisualViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height()); // Note, we specifically use the unscaled visual viewport size here as the // conversion into content-space below will apply the scale. FloatPoint anchorOffset(m_visualViewport->size()); anchorOffset.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height()); // Note, we specifically convert to the rootFrameView contents here, rather // than the layout viewport. That's because hit testing works from the // FrameView's content coordinates even if it's not the layout viewport. const FloatPoint anchorPointInContents = m_rootFrameView->frameToContents( m_visualViewport->viewportToRootFrame(anchorOffset)); Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPointInContents), innerViewRect, m_rootFrameView->frame().eventHandler()); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPointInContents - FloatPoint(m_anchorNodeBounds.location()); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
IntRect enclosingIntRect(const LayoutRect& rect) { // Empty rects with fractional x, y values turn into non-empty rects when converting to enclosing. // We need to ensure that empty rects stay empty after the conversion, because the selection code expects them to be empty. IntPoint location = flooredIntPoint(rect.minXMinYCorner()); IntPoint maxPoint = IntPoint(rect.width() ? rect.maxX().ceil() : location.x(), rect.height() ? rect.maxY().ceil() : location.y()); return IntRect(location, maxPoint - location); }
IntPoint computeTextFirstRunLocation(const RenderText& textRenderer, const Layout& layout) { auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout); auto begin = resolver.begin(); if (begin == resolver.end()) return IntPoint(); return flooredIntPoint((*begin).rect().location()); }
IntRect enclosedIntRect(const FloatRect& rect) { IntPoint location = ceiledIntPoint(rect.minXMinYCorner()); IntPoint maxPoint = flooredIntPoint(rect.maxXMaxYCorner()); IntSize size = maxPoint - location; size.clampNegativeToZero(); return IntRect(location, size); }
IntPoint computeFirstRunLocation(const RenderObject& renderer, const Layout& layout) { auto resolver = runResolver(downcast<RenderBlockFlow>(*renderer.parent()), layout); auto range = resolver.rangeForRenderer(renderer); auto begin = range.begin(); if (begin == range.end()) return IntPoint(0, 0); return flooredIntPoint((*begin).rect().location()); }
static IntPoint pinchViewportOffset(const Widget* widget) { // Event position needs to be adjusted by the pinch viewport's offset within the // main frame before being passed into the widget's convertFromContainingWindow. FrameView* rootView = toFrameView(widget->root()); if (!rootView) return IntPoint(); return flooredIntPoint(rootView->page()->frameHost().pinchViewport().visibleRect().location()); }
IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding) { IntPoint actualPoint(flooredIntPoint(point)); actualPoint -= IntSize(leftPadding, topPadding); IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding); // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1". // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects. actualPadding += IntSize(1, 1); return IntRect(actualPoint, actualPadding); }
// TODO(mustaq): Add tests for this. PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point) { m_pointerProperties = point; m_state = toPlatformTouchPointState(point.state); // This assumes convertFromRootFrame does only translations, not scales. FloatPoint floatPos = convertHitPointToRootFrame(widget, point.position); IntPoint flooredPoint = flooredIntPoint(floatPos); m_pos = widget->convertFromRootFrame(flooredPoint) + (floatPos - flooredPoint); m_screenPos = FloatPoint(point.screenPosition.x, point.screenPosition.y); m_radius = scaleSizeToWindow(widget, FloatSize(point.radiusX, point.radiusY)); m_rotationAngle = point.rotationAngle; }
void RotationViewportAnchor::setAnchor() { // FIXME: Scroll offsets are now fractional (DoublePoint and FloatPoint for the FrameView and VisualViewport // respectively. This path should be rewritten without pixel snapping. IntRect outerViewRect = m_rootFrameView->layoutViewportScrollableArea()->visibleContentRect(IncludeScrollbars); IntRect innerViewRect = enclosedIntRect(m_rootFrameView->getScrollableArea()->visibleContentRectDouble()); m_oldPageScaleFactor = m_visualViewport->scale(); m_oldMinimumPageScaleFactor = m_pageScaleConstraintsSet.finalConstraints().minimumScale; // Save the absolute location in case we won't find the anchor node, we'll fall back to that. m_visualViewportInDocument = FloatPoint(m_rootFrameView->getScrollableArea()->visibleContentRectDouble().location()); m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_normalizedVisualViewportOffset = FloatSize(); if (innerViewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (innerViewRect.location() == IntPoint::zero()) return; // Inner rectangle should be within the outer one. DCHECK(outerViewRect.contains(innerViewRect)); // Outer rectangle is used as a scale, we need positive width and height. DCHECK(!outerViewRect.isEmpty()); m_normalizedVisualViewportOffset = FloatSize(innerViewRect.location() - outerViewRect.location()); // Normalize by the size of the outer rect m_normalizedVisualViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height()); FloatSize anchorOffset(innerViewRect.size()); anchorOffset.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height()); const FloatPoint anchorPoint = FloatPoint(innerViewRect.location()) + anchorOffset; Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), innerViewRect, m_rootFrameView->frame().eventHandler()); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPoint - FloatPoint(m_anchorNodeBounds.location()); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) { FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); if (!SVGRenderSupport::pointInClippingArea(this, localPoint)) return false; return RenderBlock::nodeAtPoint(request, result, flooredIntPoint(localPoint), IntPoint(), hitTestAction); } } return false; }
FloatPoint Widget::convertFromContainingWindow(const FloatPoint& windowPoint) const { // Widgets / windows are required to be IntPoint aligned, but we may need to convert // FloatPoint values within them (eg. for event co-ordinates). IntPoint flooredPoint = flooredIntPoint(windowPoint); FloatPoint parentPoint = this->convertFromContainingWindow(flooredPoint); FloatSize windowFraction = windowPoint - flooredPoint; // Use linear interpolation handle any fractional value (eg. for iframes subject to a transform // beyond just a simple translation). // FIXME: Add FloatPoint variants of all co-ordinate space conversion APIs. if (!windowFraction.isEmpty()) { const int kFactor = 1000; IntPoint parentLineEnd = this->convertFromContainingWindow(flooredPoint + roundedIntSize(windowFraction.scaledBy(kFactor))); FloatSize parentFraction = (parentLineEnd - parentPoint).scaledBy(1.0f / kFactor); parentPoint.move(parentFraction); } return parentPoint; }
IntPoint VisualViewport::clampDocumentOffsetAtScale(const IntPoint& offset, float scale) { if (!mainFrame() || !mainFrame()->view()) return IntPoint(); FrameView* view = mainFrame()->view(); FloatSize scaledSize(m_size); scaledSize.scale(1 / scale); IntPoint visualViewportMax = flooredIntPoint(FloatSize(contentsSize()) - scaledSize); IntPoint max = view->maximumScrollPosition() + visualViewportMax; IntPoint min = view->minimumScrollPosition(); // VisualViewportMin should be (0, 0) IntPoint clamped = offset; clamped = clamped.shrunkTo(max); clamped = clamped.expandedTo(min); return clamped; }
// This method converts from the renderer's coordinate space into Blink's root frame coordinate space. // It's somewhat unique in that it takes into account DevTools emulation, which applies a scale and offset // in the root layer (see updateRootLayerTransform in WebViewImpl) as well as the overscroll effect on OSX. // This is in addition to the visual viewport "pinch-zoom" transformation and is one of the few cases where // the visual viewport is not equal to the renderer's coordinate-space. static FloatPoint convertHitPointToRootFrame(const Widget* widget, FloatPoint pointInRendererViewport) { float scale = 1; IntSize offset; IntPoint visualViewport; FloatSize overscrollOffset; if (widget) { FrameView* rootView = toFrameView(widget->root()); if (rootView) { scale = rootView->inputEventsScaleFactor(); offset = rootView->inputEventsOffsetForEmulation(); visualViewport = flooredIntPoint(rootView->page()->frameHost().visualViewport().visibleRect().location()); overscrollOffset = rootView->page()->frameHost().chromeClient().elasticOverscroll(); } } return FloatPoint( (pointInRendererViewport.x() - offset.width()) / scale + visualViewport.x() + overscrollOffset.width(), (pointInRendererViewport.y() - offset.height()) / scale + visualViewport.y() + overscrollOffset.height()); }
IntPoint ViewportAnchor::computeOrigin(const IntSize& currentViewSize) const { if (!m_anchorNode || !m_anchorNode->inDocument()) return m_viewRect.location(); const LayoutRect currentNodeBounds = m_anchorNode->boundingBox(); if (m_anchorNodeBounds == currentNodeBounds) return m_viewRect.location(); // Compute the new anchor point relative to the node position FloatSize anchorOffsetFromNode = currentNodeBounds.size(); anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(), m_anchorInNodeCoords.height()); FloatPoint anchorPoint = currentNodeBounds.location() + anchorOffsetFromNode; // Compute the new origin point relative to the new anchor point FloatSize anchorOffsetFromOrigin = currentViewSize; anchorOffsetFromOrigin.scale(m_anchorInViewCoords.width(), m_anchorInViewCoords.height()); return flooredIntPoint(anchorPoint - anchorOffsetFromOrigin); }
void ViewportAnchor::setAnchor(const IntRect& outerViewRect, const IntRect& innerViewRect, const FloatSize& anchorInInnerViewCoords) { // Preserve the inner viewport position in document in case we won't find the anchor m_pinchViewportInDocument = innerViewRect.location(); m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_anchorInInnerViewCoords = anchorInInnerViewCoords; m_normalizedPinchViewportOffset = FloatSize(); if (innerViewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (innerViewRect.location() == IntPoint::zero()) return; // Inner rectangle should be within the outer one. ASSERT(outerViewRect.contains(innerViewRect)); // Outer rectangle is used as a scale, we need positive width and height. ASSERT(!outerViewRect.isEmpty()); m_normalizedPinchViewportOffset = innerViewRect.location() - outerViewRect.location(); // Normalize by the size of the outer rect m_normalizedPinchViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height()); FloatSize anchorOffset = innerViewRect.size(); anchorOffset.scale(anchorInInnerViewCoords.width(), anchorInInnerViewCoords.height()); const FloatPoint anchorPoint = FloatPoint(innerViewRect.location()) + anchorOffset; Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), innerViewRect, m_eventHandler); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPoint - FloatPoint(m_anchorNodeBounds.location()); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
void PinchViewport::scrollIntoView(const FloatRect& rect) { if (!mainFrame() || !mainFrame()->view()) return; FrameView* view = mainFrame()->view(); float centeringOffsetX = (visibleRect().width() - rect.width()) / 2; float centeringOffsetY = (visibleRect().height() - rect.height()) / 2; FloatPoint targetOffset( rect.x() - centeringOffsetX - visibleRect().x(), rect.y() - centeringOffsetY - visibleRect().y()); view->setScrollPosition(flooredIntPoint(targetOffset)); FloatPoint remainder = FloatPoint(targetOffset - view->scrollPosition()); move(remainder); }
void ScrollableArea::scrollPositionChanged(const DoublePoint& position, ScrollType scrollType) { TRACE_EVENT0("blink", "ScrollableArea::scrollPositionChanged"); DoublePoint oldPosition = scrollPositionDouble(); DoublePoint truncatedPosition = shouldUseIntegerScrollOffset() ? flooredIntPoint(position) : position; // Tell the derived class to scroll its contents. setScrollOffset(truncatedPosition, scrollType); Scrollbar* verticalScrollbar = this->verticalScrollbar(); // Tell the scrollbars to update their thumb postions. if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) { horizontalScrollbar->offsetDidChange(); if (horizontalScrollbar->isOverlayScrollbar() && !hasLayerForHorizontalScrollbar()) { if (!verticalScrollbar) horizontalScrollbar->invalidate(); else { // If there is both a horizontalScrollbar and a verticalScrollbar, // then we must also invalidate the corner between them. IntRect boundsAndCorner = horizontalScrollbar->boundsRect(); boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrollbar->width()); horizontalScrollbar->invalidateRect(boundsAndCorner); } } } if (verticalScrollbar) { verticalScrollbar->offsetDidChange(); if (verticalScrollbar->isOverlayScrollbar() && !hasLayerForVerticalScrollbar()) verticalScrollbar->invalidate(); } if (scrollPositionDouble() != oldPosition) { // FIXME: Pass in DoubleSize. crbug.com/414283. scrollAnimator()->notifyContentAreaScrolled(toFloatSize(scrollPositionDouble() - oldPosition)); } scrollAnimator()->setCurrentPosition(toFloatPoint(position)); }
void ExternalPopupMenu::show(const FloatQuad& controlPosition, const IntSize&, int index) { IntRect rect(controlPosition.enclosingBoundingBox()); // WebCore reuses the PopupMenu of an element. // For simplicity, we do recreate the actual external popup everytime. if (m_webExternalPopupMenu) { m_webExternalPopupMenu->close(); m_webExternalPopupMenu = 0; } WebPopupMenuInfo info; getPopupMenuInfo(info, *m_popupMenuClient); if (info.items.isEmpty()) return; WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(m_localFrame.get()); m_webExternalPopupMenu = webframe->client()->createExternalPopupMenu(info, this); if (m_webExternalPopupMenu) { // FIXME: Standardize viewport coordinate conversions. crbug.com/371902. IntRect rectInViewport = m_localFrame->view()->contentsToWindow(rect); if (m_webView.pinchVirtualViewportEnabled()) rectInViewport.moveBy(-flooredIntPoint(m_webView.page()->frameHost().pinchViewport().location())); m_webExternalPopupMenu->show(rectInViewport); #if OS(MACOSX) const WebInputEvent* currentEvent = WebViewImpl::currentInputEvent(); if (currentEvent && currentEvent->type == WebInputEvent::MouseDown) { m_syntheticEvent = adoptPtr(new WebMouseEvent); *m_syntheticEvent = *static_cast<const WebMouseEvent*>(currentEvent); m_syntheticEvent->type = WebInputEvent::MouseUp; m_dispatchEventTimer.startOneShot(0, FROM_HERE); // FIXME: show() is asynchronous. If preparing a popup is slow and // a user released the mouse button before showing the popup, // mouseup and click events are correctly dispatched. Dispatching // the synthetic mouseup event is redundant in this case. } #endif } else { // The client might refuse to create a popup (when there is already one pending to be shown for example). didCancel(); } }
// TODO(mustaq): Add tests for this. PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e) { // FIXME: Widget is always toplevel, unless it's a popup. We may be able // to get rid of this once we abstract popups into a WebKit API. m_position = widget->convertFromRootFrame(flooredIntPoint(convertHitPointToRootFrame(widget, IntPoint(e.x, e.y)))); m_globalPosition = IntPoint(e.globalX, e.globalY); m_movementDelta = IntPoint(scaleDeltaToWindow(widget, e.movementX), scaleDeltaToWindow(widget, e.movementY)); m_button = static_cast<MouseButton>(e.button); m_modifiers = e.modifiers; m_timestamp = e.timeStampSeconds; m_clickCount = e.clickCount; m_pointerProperties = static_cast<WebPointerProperties>(e); switch (e.type) { case WebInputEvent::MouseMove: case WebInputEvent::MouseLeave: // synthesize a move event m_type = PlatformEvent::MouseMoved; break; case WebInputEvent::MouseDown: m_type = PlatformEvent::MousePressed; break; case WebInputEvent::MouseUp: m_type = PlatformEvent::MouseReleased; // The MouseEvent spec requires that buttons indicates the state // immediately after the event takes place. To ensure consistency // between platforms here, we explicitly clear the button that is // in the process of being released. m_modifiers &= ~toPlatformModifierFrom(e.button); break; default: ASSERT_NOT_REACHED(); } }
bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { if ((hitRules.canHitBoundingBox && !objectBoundingBox().isEmpty()) || (hitRules.canHitStroke && (style()->svgStyle().hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle().hasFill() || !hitRules.requireFill))) { FloatPoint localPoint; if (!SVGRenderSupport::transformToUserSpaceAndCheckClipping(this, localToParentTransform(), pointInParent, localPoint)) return false; if (hitRules.canHitBoundingBox && !objectBoundingBox().contains(localPoint)) return false; HitTestLocation hitTestLocation(LayoutPoint(flooredIntPoint(localPoint))); return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), hitTestAction); } } return false; }
void ViewportAnchor::computeOrigins(const FrameView& frameView, const FloatSize& innerSize, IntPoint& mainFrameOffset, FloatPoint& pinchViewportOffset) const { IntSize outerSize = frameView.visibleContentRect().size(); // Compute the viewport origins in CSS pixels relative to the document. FloatSize absPinchViewportOffset = m_normalizedPinchViewportOffset; absPinchViewportOffset.scale(outerSize.width(), outerSize.height()); FloatPoint innerOrigin = getInnerOrigin(innerSize); FloatPoint outerOrigin = innerOrigin - absPinchViewportOffset; IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize); FloatRect innerRect = FloatRect(innerOrigin, innerSize); moveToEncloseRect(outerRect, innerRect); outerRect.setLocation(frameView.adjustScrollPositionWithinRange(outerRect.location())); moveIntoRect(innerRect, outerRect); mainFrameOffset = outerRect.location(); pinchViewportOffset = FloatPoint(innerRect.location() - outerRect.location()); }
WebRenderObject::WebRenderObject(RenderObject* renderer, bool shouldIncludeDescendants) { m_name = renderer->renderName(); m_textLength = 0; if (Node* node = renderer->node()) { if (is<Element>(*node)) { Element& element = downcast<Element>(*node); m_elementTagName = element.tagName(); m_elementID = element.getIdAttribute(); if (element.isStyledElement() && element.hasClass()) { Vector<RefPtr<API::Object>> classNames; classNames.reserveInitialCapacity(element.classNames().size()); for (size_t i = 0, size = element.classNames().size(); i < size; ++i) classNames.append(API::String::create(element.classNames()[i])); m_elementClassNames = API::Array::create(WTFMove(classNames)); } } if (node->isTextNode()) { String value = node->nodeValue(); m_textLength = value.length(); const int maxSnippetLength = 40; if (value.length() > maxSnippetLength) m_textSnippet = value.substring(0, maxSnippetLength); else m_textSnippet = value; } } // FIXME: broken with transforms m_absolutePosition = flooredIntPoint(renderer->localToAbsolute()); if (is<RenderBox>(*renderer)) m_frameRect = snappedIntRect(downcast<RenderBox>(*renderer).frameRect()); else if (is<RenderText>(*renderer)) { m_frameRect = downcast<RenderText>(*renderer).linesBoundingBox(); m_frameRect.setLocation(downcast<RenderText>(*renderer).firstRunLocation()); } else if (is<RenderInline>(*renderer)) m_frameRect = IntRect(downcast<RenderInline>(*renderer).borderBoundingBox()); if (!shouldIncludeDescendants) return; Vector<RefPtr<API::Object>> children; for (RenderObject* coreChild = renderer->firstChildSlow(); coreChild; coreChild = coreChild->nextSibling()) { RefPtr<WebRenderObject> child = adoptRef(new WebRenderObject(coreChild, shouldIncludeDescendants)); children.append(WTFMove(child)); } if (is<RenderWidget>(*renderer)) { if (Widget* widget = downcast<RenderWidget>(*renderer).widget()) { if (is<FrameView>(*widget)) { FrameView& frameView = downcast<FrameView>(*widget); if (RenderView* coreContentRenderer = frameView.frame().contentRenderer()) { RefPtr<WebRenderObject> contentRenderer = adoptRef(new WebRenderObject(coreContentRenderer, shouldIncludeDescendants)); children.append(WTFMove(contentRenderer)); } } } } m_children = API::Array::create(WTFMove(children)); }
IntPoint scrollPosition() const override { return flooredIntPoint(m_scrollPosition); }
IntPoint PinchViewport::maximumScrollPosition() const { return flooredIntPoint(FloatSize(contentsSize()) - visibleRect().size()); }