Пример #1
0
FloatPoint RotationViewportAnchor::getInnerOrigin(
    const FloatSize& innerSize) const {
  if (!m_anchorNode || !m_anchorNode->isConnected())
    return m_visualViewportInDocument;

  const LayoutRect currentNodeBounds = m_anchorNode->boundingBox();
  if (m_anchorNodeBounds == currentNodeBounds)
    return m_visualViewportInDocument;

  RootFrameViewport* rootFrameViewport =
      m_rootFrameView->getRootFrameViewport();
  const LayoutRect currentNodeBoundsInLayoutViewport =
      rootFrameViewport->rootContentsToLayoutViewportContents(
          *m_rootFrameView.get(), currentNodeBounds);

  // Compute the new anchor point relative to the node position
  FloatSize anchorOffsetFromNode(currentNodeBoundsInLayoutViewport.size());
  anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(),
                             m_anchorInNodeCoords.height());
  FloatPoint anchorPoint =
      FloatPoint(currentNodeBoundsInLayoutViewport.location()) +
      anchorOffsetFromNode;

  // Compute the new origin point relative to the new anchor point
  FloatSize anchorOffsetFromOrigin = innerSize;
  anchorOffsetFromOrigin.scale(m_anchorInInnerViewCoords.width(),
                               m_anchorInInnerViewCoords.height());
  return anchorPoint - anchorOffsetFromOrigin;
}
Пример #2
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());
}
Пример #3
0
void VisualViewport::notifyRootFrameViewport() const {
  if (!mainFrame() || !mainFrame()->view())
    return;

  RootFrameViewport* rootFrameViewport =
      mainFrame()->view()->getRootFrameViewport();

  if (!rootFrameViewport)
    return;

  rootFrameViewport->didUpdateVisualViewport();
}
Пример #4
0
IntRect VisualViewport::visibleContentRect(
    IncludeScrollbarsInRect scrollbarInclusion) const {
  // TODO(ymalik): We're losing precision here and below. visibleRect should
  // be replaced with visibleContentRect.
  IntRect rect = IntRect(visibleRect());
  if (scrollbarInclusion == ExcludeScrollbars) {
    RootFrameViewport* rootFrameViewport =
        mainFrame()->view()->getRootFrameViewport();
    DCHECK(rootFrameViewport);
    rect.contract(rootFrameViewport->verticalScrollbarWidth() / m_scale,
                  rootFrameViewport->horizontalScrollbarHeight() / m_scale);
  }
  return rect;
}
Пример #5
0
// Tests that setting an alternate layout viewport scrolls the alternate
// instead of the original.
TEST_F(RootFrameViewportTest, SetAlternateLayoutViewport) {
  IntSize viewportSize(100, 100);
  RootFrameViewStub* layoutViewport =
      RootFrameViewStub::create(viewportSize, IntSize(200, 300));
  VisualViewportStub* visualViewport =
      VisualViewportStub::create(viewportSize, viewportSize);

  RootFrameViewStub* alternateScroller =
      RootFrameViewStub::create(viewportSize, IntSize(600, 500));

  RootFrameViewport* rootFrameViewport =
      RootFrameViewport::create(*visualViewport, *layoutViewport);

  visualViewport->setScale(2);

  rootFrameViewport->setScrollOffset(ScrollOffset(100, 100), UserScroll);
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), visualViewport->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), layoutViewport->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(100, 100), rootFrameViewport->getScrollOffset());

  rootFrameViewport->setLayoutViewport(*alternateScroller);
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), visualViewport->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(0, 0), alternateScroller->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), rootFrameViewport->getScrollOffset());

  rootFrameViewport->setScrollOffset(ScrollOffset(200, 200), UserScroll);
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), visualViewport->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(150, 150), alternateScroller->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(200, 200), rootFrameViewport->getScrollOffset());
  EXPECT_SIZE_EQ(ScrollOffset(50, 50), layoutViewport->getScrollOffset());

  EXPECT_SIZE_EQ(ScrollOffset(550, 450),
                 rootFrameViewport->maximumScrollOffset());
}
Пример #6
0
ScrollableArea& RotationViewportAnchor::layoutViewport() const {
  RootFrameViewport* rootFrameViewport =
      m_rootFrameView->getRootFrameViewport();
  DCHECK(rootFrameViewport);
  return rootFrameViewport->layoutViewport();
}
Пример #7
0
void RotationViewportAnchor::setAnchor() {
  RootFrameViewport* rootFrameViewport =
      m_rootFrameView->getRootFrameViewport();
  DCHECK(rootFrameViewport);

  IntRect outerViewRect =
      layoutViewport().visibleContentRect(IncludeScrollbars);
  IntRect innerViewRect = rootFrameViewport->visibleContentRect();

  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();

  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());

  FloatPoint anchorOffset(innerViewRect.size());
  anchorOffset.scale(m_anchorInInnerViewCoords.width(),
                     m_anchorInInnerViewCoords.height());

  const FloatPoint anchorPointInContents = m_rootFrameView->rootFrameToContents(
      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());
}