Пример #1
0
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);
}
Пример #4
0
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());
    }
}
Пример #5
0
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;
}
Пример #6
0
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());
}
Пример #7
0
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());
}
Пример #8
0
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);
}
Пример #9
0
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());
}
Пример #10
0
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());
}
Пример #12
0
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());
}
Пример #13
0
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());
}
Пример #16
0
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;
}
Пример #17
0
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());
}
Пример #20
0
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);
}
Пример #21
0
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());
}
Пример #22
0
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));
}
Пример #24
0
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();
    }
}
Пример #26
0
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;
}
Пример #27
0
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());
}
Пример #28
0
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));
}
Пример #29
0
 IntPoint scrollPosition() const override { return flooredIntPoint(m_scrollPosition); }
Пример #30
0
IntPoint PinchViewport::maximumScrollPosition() const
{
    return flooredIntPoint(FloatSize(contentsSize()) - visibleRect().size());
}