Esempio n. 1
0
void
APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
                                    FrameMetrics& aMetrics)
{
  // Precondition checks
  MOZ_ASSERT(aUtils);
  MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
  if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }

  // Set the scroll port size, which determines the scroll range. For example if
  // a 500-pixel document is shown in a 100-pixel frame, the scroll port length would
  // be 100, and gecko would limit the maximum scroll offset to 400 (so as to prevent
  // overscroll). Note that if the content here was zoomed to 2x, the document would
  // be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
  // scroll range would be 900. Therefore this calculation depends on the zoom applied
  // to the content relative to the container.
  // Note that this needs to happen before scrolling the frame (in UpdateFrameCommon),
  // otherwise the scroll position may get clamped incorrectly.
  CSSSize scrollPort = aMetrics.CalculateCompositedSizeInCssPixels();
  aUtils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);

  nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
  ScrollFrame(content, aMetrics);

  // The pres shell resolution is updated by the the async zoom since the
  // last paint.
  float presShellResolution = aMetrics.GetPresShellResolution()
                            * aMetrics.GetAsyncZoom().scale;
  aUtils->SetResolutionAndScaleTo(presShellResolution, presShellResolution);

  SetDisplayPortMargins(aUtils, content, aMetrics);
}
void
APZCCallbackHelper::UpdateRootFrame(FrameMetrics& aMetrics)
{
  if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }
  nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
  if (!content) {
    return;
  }

  nsCOMPtr<nsIPresShell> shell = GetPresShell(content);
  if (!shell || aMetrics.GetPresShellId() != shell->GetPresShellId()) {
    return;
  }

  MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());

  if (gfxPrefs::APZAllowZooming()) {
    // If zooming is disabled then we don't really want to let APZ fiddle
    // with these things. In theory setting the resolution here should be a
    // no-op, but setting the SPCSPS is bad because it can cause a stale value
    // to be returned by window.innerWidth/innerHeight (see bug 1187792).

    float presShellResolution = nsLayoutUtils::GetResolution(shell);

    // If the pres shell resolution has changed on the content side side
    // the time this repaint request was fired, consider this request out of date
    // and drop it; setting a zoom based on the out-of-date resolution can have
    // the effect of getting us stuck with the stale resolution.
    if (presShellResolution != aMetrics.GetPresShellResolution()) {
      return;
    }

    // Set the scroll port size, which determines the scroll range. For example if
    // a 500-pixel document is shown in a 100-pixel frame, the scroll port length would
    // be 100, and gecko would limit the maximum scroll offset to 400 (so as to prevent
    // overscroll). Note that if the content here was zoomed to 2x, the document would
    // be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
    // scroll range would be 900. Therefore this calculation depends on the zoom applied
    // to the content relative to the container.
    // Note that this needs to happen before scrolling the frame (in UpdateFrameCommon),
    // otherwise the scroll position may get clamped incorrectly.
    CSSSize scrollPort = aMetrics.CalculateCompositedSizeInCssPixels();
    nsLayoutUtils::SetScrollPositionClampingScrollPortSize(shell, scrollPort);

    // The pres shell resolution is updated by the the async zoom since the
    // last paint.
    presShellResolution = aMetrics.GetPresShellResolution()
                        * aMetrics.GetAsyncZoom().scale;
    nsLayoutUtils::SetResolutionAndScaleTo(shell, presShellResolution);
  }

  // Do this as late as possible since scrolling can flush layout. It also
  // adjusts the display port margins, so do it before we set those.
  ScrollFrame(content, aMetrics);

  SetDisplayPortMargins(shell, content, aMetrics);
}
Esempio n. 3
0
// APZC sends us this request when we need to update the display port on
// the scrollable frame the apzc is managing.
void
APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
#ifdef DEBUG_CONTROLLER
  WinUtils::Log("APZController::RequestContentRepaint scrollid=%I64d",
    aFrameMetrics.GetScrollId());
#endif

  // This must be on the gecko thread since we access the dom
  MOZ_ASSERT(NS_IsMainThread());

#ifdef DEBUG_CONTROLLER
  WinUtils::Log("APZController: mScrollOffset: %f %f", aFrameMetrics.mScrollOffset.x,
    aFrameMetrics.mScrollOffset.y);
#endif

  nsCOMPtr<nsIDocument> subDocument;
  nsCOMPtr<nsIContent> targetContent;
  if (!GetDOMTargets(aFrameMetrics.GetScrollId(),
                     subDocument, targetContent)) {
    return;
  }

  // If we're dealing with a sub frame or content editable element,
  // call UpdateSubFrame.
  if (targetContent) {
#ifdef DEBUG_CONTROLLER
    WinUtils::Log("APZController: detected subframe or content editable");
#endif
    FrameMetrics metrics = aFrameMetrics;
    mozilla::layers::APZCCallbackHelper::UpdateSubFrame(targetContent, metrics);
    return;
  }

#ifdef DEBUG_CONTROLLER
  WinUtils::Log("APZController: detected tab");
#endif

  // We're dealing with a tab, call UpdateRootFrame.
  nsCOMPtr<nsIDOMWindowUtils> utils;
  nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
  if (window) {
    utils = do_GetInterface(window);
    if (utils) {
      FrameMetrics metrics = aFrameMetrics;
      mozilla::layers::APZCCallbackHelper::UpdateRootFrame(utils, metrics);

#ifdef DEBUG_CONTROLLER
      WinUtils::Log("APZController: %I64d mDisplayPortMargins: %0.2f %0.2f %0.2f %0.2f",
        metrics.GetScrollId(),
        metrics.GetDisplayPortMargins().left,
        metrics.GetDisplayPortMargins().top,
        metrics.GetDisplayPortMargins().right,
        metrics.GetDisplayPortMargins().bottom);
#endif
    }
  }
}
Esempio n. 4
0
void
APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent,
                                   FrameMetrics& aMetrics)
{
    // Precondition checks
    MOZ_ASSERT(aContent);
    MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
    if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
        return;
    }

    nsCOMPtr<nsIDOMWindowUtils> utils = GetDOMWindowUtils(aContent);
    if (!utils) {
        return;
    }

    // We currently do not support zooming arbitrary subframes. They can only
    // be scrolled, so here we only have to set the scroll position and displayport.

    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
    bool scrollUpdated = false;
    CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics.GetScrollOffset(), scrollUpdated);

    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
    if (element) {
        if (scrollUpdated) {
            AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
        } else {
            RecenterDisplayPort(aMetrics);
        }
        gfx::IntSize alignment = gfxPrefs::LayersTilesEnabled()
            ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) :
              gfx::IntSize(0, 0);
        LayerMargin margins = aMetrics.GetDisplayPortMargins();
        utils->SetDisplayPortMarginsForElement(margins.left,
                                               margins.top,
                                               margins.right,
                                               margins.bottom,
                                               alignment.width,
                                               alignment.height,
                                               element, 0);
        CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
        nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(),
                    baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(),
                    baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
                    baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
        nsLayoutUtils::SetDisplayPortBaseIfNotSet(aContent, base);
    }

    aMetrics.SetScrollOffset(actualScrollOffset);
}
Esempio n. 5
0
void
APZCCallbackHelper::UpdateRootFrame(FrameMetrics& aMetrics)
{
  if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }
  nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
  if (!content) {
    return;
  }

  nsCOMPtr<nsIPresShell> shell = GetPresShell(content);
  if (!shell || aMetrics.GetPresShellId() != shell->GetPresShellId()) {
    return;
  }

  MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());

  if (gfxPrefs::APZAllowZooming()) {
    // If zooming is disabled then we don't really want to let APZ fiddle
    // with these things. In theory setting the resolution here should be a
    // no-op, but setting the SPCSPS is bad because it can cause a stale value
    // to be returned by window.innerWidth/innerHeight (see bug 1187792).

    float presShellResolution = shell->GetResolution();

    // If the pres shell resolution has changed on the content side side
    // the time this repaint request was fired, consider this request out of date
    // and drop it; setting a zoom based on the out-of-date resolution can have
    // the effect of getting us stuck with the stale resolution.
    if (presShellResolution != aMetrics.GetPresShellResolution()) {
      return;
    }

    // The pres shell resolution is updated by the the async zoom since the
    // last paint.
    presShellResolution = aMetrics.GetPresShellResolution()
                        * aMetrics.GetAsyncZoom().scale;
    shell->SetResolutionAndScaleTo(presShellResolution);
  }

  // Do this as late as possible since scrolling can flush layout. It also
  // adjusts the display port margins, so do it before we set those.
  ScrollFrame(content, aMetrics);

  MOZ_ASSERT(nsLayoutUtils::HasDisplayPort(content));
  SetDisplayPortMargins(shell, content, aMetrics);
  SetPaintRequestTime(content, aMetrics.GetPaintRequestTime());
}
void
ChromeProcessController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (aFrameMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }

  nsCOMPtr<nsIContent> targetContent = nsLayoutUtils::FindContentFor(aFrameMetrics.GetScrollId());
  if (targetContent) {
    FrameMetrics metrics = aFrameMetrics;
    APZCCallbackHelper::UpdateSubFrame(targetContent, metrics);
  }
}
bool
ClientTiledPaintedLayer::IsScrollingOnCompositor(const FrameMetrics& aParentMetrics)
{
  CompositorChild* compositor = nullptr;
  if (Manager() && Manager()->AsClientLayerManager()) {
    compositor = Manager()->AsClientLayerManager()->GetCompositorChild();
  }

  if (!compositor) {
    return false;
  }

  FrameMetrics compositorMetrics;
  if (!compositor->LookupCompositorFrameMetrics(aParentMetrics.GetScrollId(),
                                                compositorMetrics)) {
    return false;
  }

  // 1 is a tad high for a fuzzy equals epsilon however if our scroll delta
  // is so small then we have nothing to gain from using paint heuristics.
  float COORDINATE_EPSILON = 1.f;

  return !FuzzyEqualsAdditive(compositorMetrics.GetScrollOffset().x,
                              aParentMetrics.GetScrollOffset().x,
                              COORDINATE_EPSILON) ||
         !FuzzyEqualsAdditive(compositorMetrics.GetScrollOffset().y,
                              aParentMetrics.GetScrollOffset().y,
                              COORDINATE_EPSILON);
}
void
APZCCallbackHelper::UpdateRootFrame(nsIPresShell* aPresShell,
                                    FrameMetrics& aMetrics)
{
  // Precondition checks
  MOZ_ASSERT(aPresShell);
  MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
  if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }

  float presShellResolution = nsLayoutUtils::GetResolution(aPresShell);

  // If the pres shell resolution has changed on the content side side
  // the time this repaint request was fired, consider this request out of date
  // and drop it; setting a zoom based on the out-of-date resolution can have
  // the effect of getting us stuck with the stale resolution.
  if (presShellResolution != aMetrics.GetPresShellResolution()) {
    return;
  }

  // Set the scroll port size, which determines the scroll range. For example if
  // a 500-pixel document is shown in a 100-pixel frame, the scroll port length would
  // be 100, and gecko would limit the maximum scroll offset to 400 (so as to prevent
  // overscroll). Note that if the content here was zoomed to 2x, the document would
  // be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
  // scroll range would be 900. Therefore this calculation depends on the zoom applied
  // to the content relative to the container.
  // Note that this needs to happen before scrolling the frame (in UpdateFrameCommon),
  // otherwise the scroll position may get clamped incorrectly.
  CSSSize scrollPort = aMetrics.CalculateCompositedSizeInCssPixels();
  nsLayoutUtils::SetScrollPositionClampingScrollPortSize(aPresShell, scrollPort);

  // The pres shell resolution is updated by the the async zoom since the
  // last paint.
  presShellResolution = aMetrics.GetPresShellResolution()
                      * aMetrics.GetAsyncZoom().scale;
  nsLayoutUtils::SetResolutionAndScaleTo(aPresShell, presShellResolution);

  // Do this as late as possible since scrolling can flush layout. It also
  // adjusts the display port margins, so do it before we set those.
  nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
  ScrollFrame(content, aMetrics);

  SetDisplayPortMargins(aPresShell, content, aMetrics);
}
Esempio n. 9
0
void
AppendToString(std::stringstream& aStream, const FrameMetrics& m,
               const char* pfx, const char* sfx, bool detailed)
{
  aStream << pfx;
  AppendToString(aStream, m.GetCompositionBounds(), "{ [cb=");
  AppendToString(aStream, m.GetScrollableRect(), "] [sr=");
  AppendToString(aStream, m.GetScrollOffset(), "] [s=");
  if (m.GetDoSmoothScroll()) {
    AppendToString(aStream, m.GetSmoothScrollOffset(), "] [ss=");
  }
  AppendToString(aStream, m.GetDisplayPort(), "] [dp=");
  AppendToString(aStream, m.GetCriticalDisplayPort(), "] [cdp=");
  AppendToString(aStream, m.GetBackgroundColor(), "] [color=");
  if (!detailed) {
    AppendToString(aStream, m.GetScrollId(), "] [scrollId=");
    if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) {
      AppendToString(aStream, m.GetScrollParentId(), "] [scrollParent=");
    }
    if (m.IsRootContent()) {
      aStream << "] [rcd";
    }
    if (m.HasClipRect()) {
      AppendToString(aStream, m.ClipRect(), "] [clip=");
    }
    AppendToString(aStream, m.GetZoom(), "] [z=", "] }");
  } else {
    AppendToString(aStream, m.GetDisplayPortMargins(), " [dpm=");
    aStream << nsPrintfCString("] um=%d", m.GetUseDisplayPortMargins()).get();
    AppendToString(aStream, m.GetRootCompositionSize(), "] [rcs=");
    AppendToString(aStream, m.GetViewport(), "] [v=");
    aStream << nsPrintfCString("] [z=(ld=%.3f r=%.3f",
            m.GetDevPixelsPerCSSPixel().scale,
            m.GetPresShellResolution()).get();
    AppendToString(aStream, m.GetCumulativeResolution(), " cr=");
    AppendToString(aStream, m.GetZoom(), " z=");
    AppendToString(aStream, m.GetExtraResolution(), " er=");
    aStream << nsPrintfCString(")] [u=(%d %d %lu)",
            m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(),
            m.GetScrollGeneration()).get();
    AppendToString(aStream, m.GetScrollParentId(), "] [p=");
    aStream << nsPrintfCString("] [i=(%ld %lld %d)] }",
            m.GetPresShellId(), m.GetScrollId(), m.IsRootContent()).get();
  }
  aStream << sfx;
}
Esempio n. 10
0
FrameMetrics::ViewID
CompositorChild::SharedFrameMetricsData::GetViewID()
{
  FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory());
  MOZ_ASSERT(frame);
  // Not locking to read of mScrollId since it should not change after being
  // initially set.
  return frame->GetScrollId();
}
Esempio n. 11
0
void
APZCCallbackHelper::UpdateSubFrame(FrameMetrics& aMetrics)
{
  if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
    return;
  }
  nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
  if (!content) {
    return;
  }

  MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());

  // We don't currently support zooming for subframes, so nothing extra
  // needs to be done beyond the tasks common to this and UpdateRootFrame.
  ScrollFrame(content, aMetrics);
  if (nsCOMPtr<nsIPresShell> shell = GetPresShell(content)) {
    SetDisplayPortMargins(shell, content, aMetrics);
  }
}
Esempio n. 12
0
void
APZCCallbackHelper::UpdateCallbackTransform(const FrameMetrics& aApzcMetrics, const FrameMetrics& aActualMetrics)
{
    nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aApzcMetrics.GetScrollId());
    if (!content) {
        return;
    }
    CSSPoint scrollDelta = aApzcMetrics.GetScrollOffset() - aActualMetrics.GetScrollOffset();
    content->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(scrollDelta),
                         nsINode::DeleteProperty<CSSPoint>);
}
void
APZCCallbackHandler::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
    MOZ_ASSERT(NS_IsMainThread());
    MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);

    if (aFrameMetrics.GetIsRoot()) {
        nsIDOMWindowUtils* utils = GetDOMWindowUtils();
        if (utils && APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
            FrameMetrics metrics = aFrameMetrics;
            APZCCallbackHelper::UpdateRootFrame(utils, metrics);
        }
    } else {
        // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
        // This requires special handling.
        nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aFrameMetrics.GetScrollId());
        if (content) {
            FrameMetrics newSubFrameMetrics(aFrameMetrics);
            APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
        }
    }
}
Esempio n. 14
0
/**
 * Scroll the scroll frame associated with |aContent| to the scroll position
 * requested in |aMetrics|.
 * The scroll offset in |aMetrics| is updated to reflect the actual scroll
 * position.
 * The displayport stored in |aMetrics| and the callback-transform stored on
 * the content are updated to reflect any difference between the requested
 * and actual scroll positions.
 */
static void
ScrollFrame(nsIContent* aContent,
            FrameMetrics& aMetrics)
{
  // Scroll the window to the desired spot
  nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
  if (sf) {
    sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
  }

  bool scrollUpdated = false;
  CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
  CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);

  if (scrollUpdated) {
    if (aMetrics.IsScrollInfoLayer()) {
      // In cases where the APZ scroll offset is different from the content scroll
      // offset, we want to interpret the margins as relative to the APZ scroll
      // offset except when the frame is not scrollable by APZ. Therefore, if the
      // layer is a scroll info layer, we leave the margins as-is and they will
      // be interpreted as relative to the content scroll offset.
      if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
        frame->SchedulePaint();
      }
    } else {
      // Correct the display port due to the difference between mScrollOffset and the
      // actual scroll offset.
      APZCCallbackHelper::AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
    }
  } else {
    // For whatever reason we couldn't update the scroll offset on the scroll frame,
    // which means the data APZ used for its displayport calculation is stale. Fall
    // back to a sane default behaviour. Note that we don't tile-align the recentered
    // displayport because tile-alignment depends on the scroll position, and the
    // scroll position here is out of our control. See bug 966507 comment 21 for a
    // more detailed explanation.
    RecenterDisplayPort(aMetrics);
  }

  aMetrics.SetScrollOffset(actualScrollOffset);

  // APZ transforms inputs assuming we applied the exact scroll offset it
  // requested (|apzScrollOffset|). Since we may not have, record the difference
  // between what APZ asked for and what we actually applied, and apply it to
  // input events to compensate.
  if (aContent) {
    CSSPoint scrollDelta = apzScrollOffset - actualScrollOffset;
    aContent->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(scrollDelta),
                          nsINode::DeleteProperty<CSSPoint>);
  }
}
Esempio n. 15
0
void
AppendToString(std::stringstream& aStream, const FrameMetrics& m,
               const char* pfx, const char* sfx, bool detailed)
{
  aStream << pfx;
  AppendToString(aStream, m.mCompositionBounds, "{ cb=");
  AppendToString(aStream, m.mScrollableRect, " sr=");
  AppendToString(aStream, m.GetScrollOffset(), " s=");
  if (m.GetDoSmoothScroll()) {
    AppendToString(aStream, m.GetSmoothScrollOffset(), " ss=");
  }
  AppendToString(aStream, m.mDisplayPort, " dp=");
  AppendToString(aStream, m.mCriticalDisplayPort, " cdp=");
  AppendToString(aStream, m.GetBackgroundColor(), " color=");
  if (!detailed) {
    AppendToString(aStream, m.GetScrollId(), " scrollId=");
    if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) {
      AppendToString(aStream, m.GetScrollParentId(), " scrollParent=");
    }
    aStream << nsPrintfCString(" z=%.3f }", m.GetZoom().scale).get();
  } else {
    AppendToString(aStream, m.GetDisplayPortMargins(), " dpm=");
    aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get();
    AppendToString(aStream, m.GetRootCompositionSize(), " rcs=");
    AppendToString(aStream, m.GetViewport(), " v=");
    aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f er=%.3f)",
            m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution,
            m.mCumulativeResolution.scale, m.GetZoom().scale,
            m.GetExtraResolution().scale).get();
    aStream << nsPrintfCString(" u=(%d %d %lu)",
            m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(),
            m.GetScrollGeneration()).get();
    AppendToString(aStream, m.GetScrollParentId(), " p=");
    aStream << nsPrintfCString(" i=(%ld %lld) }",
            m.GetPresShellId(), m.GetScrollId()).get();
  }
  aStream << sfx;
}
Esempio n. 16
0
// APZC sends us this request when we need to update the display port on
// the scrollable frame the apzc is managing.
void
APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
  if (!mWidgetListener) {
    NS_WARNING("Can't update display port, !mWidgetListener");
    return;
  }

#ifdef DEBUG_CONTROLLER
  WinUtils::Log("APZController::RequestContentRepaint scrollid=%I64d",
    aFrameMetrics.GetScrollId());
#endif
  nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics,
                                                            mWidgetListener);
  if (!NS_IsMainThread()) {
    NS_DispatchToMainThread(r1);
  } else {
    r1->Run();
  }
}
Esempio n. 17
0
/**
 * Scroll the scroll frame associated with |aContent| to the scroll position
 * requested in |aMetrics|.
 * The scroll offset in |aMetrics| is updated to reflect the actual scroll
 * position.
 * The displayport stored in |aMetrics| and the callback-transform stored on
 * the content are updated to reflect any difference between the requested
 * and actual scroll positions.
 */
static void
ScrollFrame(nsIContent* aContent,
            FrameMetrics& aMetrics)
{
  // Scroll the window to the desired spot
  nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
  bool scrollUpdated = false;
  CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
  CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);

  if (scrollUpdated) {
    // Correct the display port due to the difference between mScrollOffset and the
    // actual scroll offset.
    AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
  } else {
    // For whatever reason we couldn't update the scroll offset on the scroll frame,
    // which means the data APZ used for its displayport calculation is stale. Fall
    // back to a sane default behaviour. Note that we don't tile-align the recentered
    // displayport because tile-alignment depends on the scroll position, and the
    // scroll position here is out of our control. See bug 966507 comment 21 for a
    // more detailed explanation.
    RecenterDisplayPort(aMetrics);
  }

  aMetrics.SetScrollOffset(actualScrollOffset);

  // APZ transforms inputs assuming we applied the exact scroll offset it
  // requested (|apzScrollOffset|). Since we may not have, record the difference
  // between what APZ asked for and what we actually applied, and apply it to
  // input events to compensate.
  if (aContent) {
    CSSPoint scrollDelta = apzScrollOffset - actualScrollOffset;
    aContent->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(scrollDelta),
                          nsINode::DeleteProperty<CSSPoint>);
  }
}
Esempio n. 18
0
void
APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
                                    FrameMetrics& aMetrics)
{
    // Precondition checks
    MOZ_ASSERT(aUtils);
    MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
    if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
        return;
    }

    // Set the scroll port size, which determines the scroll range. For example if
    // a 500-pixel document is shown in a 100-pixel frame, the scroll port length would
    // be 100, and gecko would limit the maximum scroll offset to 400 (so as to prevent
    // overscroll). Note that if the content here was zoomed to 2x, the document would
    // be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
    // scroll range would be 900. Therefore this calculation depends on the zoom applied
    // to the content relative to the container.
    CSSSize scrollPort = aMetrics.CalculateCompositedSizeInCssPixels();
    aUtils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);

    // Scroll the window to the desired spot
    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
    bool scrollUpdated = false;
    CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics.GetScrollOffset(), scrollUpdated);

    if (scrollUpdated) {
        // Correct the display port due to the difference between mScrollOffset and the
        // actual scroll offset.
        AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
    } else {
        // For whatever reason we couldn't update the scroll offset on the scroll frame,
        // which means the data APZ used for its displayport calculation is stale. Fall
        // back to a sane default behaviour. Note that we don't tile-align the recentered
        // displayport because tile-alignment depends on the scroll position, and the
        // scroll position here is out of our control. See bug 966507 comment 21 for a
        // more detailed explanation.
        RecenterDisplayPort(aMetrics);
    }

    aMetrics.SetScrollOffset(actualScrollOffset);

    // The pres shell resolution is updated by the the async zoom since the
    // last paint.
    float presShellResolution = aMetrics.GetPresShellResolution()
                              * aMetrics.GetAsyncZoom().scale;
    aUtils->SetResolutionAndScaleTo(presShellResolution, presShellResolution);

    // Finally, we set the displayport.
    nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
    if (!content) {
        return;
    }
    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(content);
    if (!element) {
        return;
    }

    ScreenMargin margins = aMetrics.GetDisplayPortMargins();
    aUtils->SetDisplayPortMarginsForElement(margins.left,
                                            margins.top,
                                            margins.right,
                                            margins.bottom,
                                            element, 0);
    CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
    nsRect base(0, 0,
                baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
                baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
    nsLayoutUtils::SetDisplayPortBaseIfNotSet(content, base);
}
Esempio n. 19
0
// Recursively create a new array of scrollables, preserving any scrollables
// that are still in the layer tree.
//
// aXScale and aYScale are used to calculate any values that need to be in
// chrome-document CSS pixels and aren't part of the rendering loop, such as
// the initial scroll offset for a new view.
static void
BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
             nsFrameLoader* aFrameLoader, Layer* aLayer,
             float aXScale = 1, float aYScale = 1,
             float aAccConfigXScale = 1, float aAccConfigYScale = 1)
{
  ContainerLayer* container = aLayer->AsContainerLayer();
  if (!container)
    return;
  const FrameMetrics metrics = container->GetFrameMetrics();
  const ViewID scrollId = metrics.GetScrollId();
  gfx3DMatrix transform;
  To3DMatrix(aLayer->GetTransform(), transform);
  aXScale *= GetXScale(transform);
  aYScale *= GetYScale(transform);

  if (metrics.IsScrollable()) {
    nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
                                        ->PresContext()->AppUnitsPerDevPixel();
    nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel.scale;
    nsContentView* view = FindViewForId(oldContentViews, scrollId);
    if (view) {
      // View already exists. Be sure to propagate scales for any values
      // that need to be calculated something in chrome-doc CSS pixels.
      ViewConfig config = view->GetViewConfig();
      aXScale *= config.mXScale;
      aYScale *= config.mYScale;
      view->mFrameLoader = aFrameLoader;
      // If scale has changed, then we should update
      // current scroll offset to new scaled value
      if (aAccConfigXScale != view->mParentScaleX ||
          aAccConfigYScale != view->mParentScaleY) {
        float xscroll = 0, yscroll = 0;
        view->GetScrollX(&xscroll);
        view->GetScrollY(&yscroll);
        xscroll = xscroll * (aAccConfigXScale / view->mParentScaleX);
        yscroll = yscroll * (aAccConfigYScale / view->mParentScaleY);
        view->ScrollTo(xscroll, yscroll);
        view->mParentScaleX = aAccConfigXScale;
        view->mParentScaleY = aAccConfigYScale;
      }
      // Collect only config scale values for scroll compensation
      aAccConfigXScale *= config.mXScale;
      aAccConfigYScale *= config.mYScale;
    } else {
      // View doesn't exist, so generate one. We start the view scroll offset at
      // the same position as the framemetric's scroll offset from the layer.
      // The default scale is 1, so no need to propagate scale down.
      ViewConfig config;
      config.mScrollOffset = nsPoint(
        NSIntPixelsToAppUnits(metrics.GetScrollOffset().x, auPerCSSPixel) * aXScale,
        NSIntPixelsToAppUnits(metrics.GetScrollOffset().y, auPerCSSPixel) * aYScale);
      view = new nsContentView(aFrameLoader, scrollId, metrics.mIsRoot, config);
      view->mParentScaleX = aAccConfigXScale;
      view->mParentScaleY = aAccConfigYScale;
    }

    // I don't know what units mViewportSize is in, hence use ToUnknownRect
    // here to mark the current frontier in type info propagation
    gfx::Rect viewport = metrics.mViewport.ToUnknownRect();
    view->mViewportSize = nsSize(
      NSIntPixelsToAppUnits(viewport.width, auPerDevPixel) * aXScale,
      NSIntPixelsToAppUnits(viewport.height, auPerDevPixel) * aYScale);
    view->mContentSize = nsSize(
      NSFloatPixelsToAppUnits(metrics.mScrollableRect.width, auPerCSSPixel) * aXScale,
      NSFloatPixelsToAppUnits(metrics.mScrollableRect.height, auPerCSSPixel) * aYScale);

    newContentViews[scrollId] = view;
  }

  for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
    BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child,
                 aXScale, aYScale, aAccConfigXScale, aAccConfigYScale);
  }
}
Esempio n. 20
0
void
APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
                                    FrameMetrics& aMetrics)
{
    // Precondition checks
    MOZ_ASSERT(aUtils);
    MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
    if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
        return;
    }

    // Set the scroll port size, which determines the scroll range. For example if
    // a 500-pixel document is shown in a 100-pixel frame, the scroll port length would
    // be 100, and gecko would limit the maximum scroll offset to 400 (so as to prevent
    // overscroll). Note that if the content here was zoomed to 2x, the document would
    // be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
    // scroll range would be 900. Therefore this calculation depends on the zoom applied
    // to the content relative to the container.
    CSSSize scrollPort = aMetrics.CalculateCompositedSizeInCssPixels();
    aUtils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);

    // Scroll the window to the desired spot
    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
    bool scrollUpdated = false;
    CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics.GetScrollOffset(), scrollUpdated);

    if (scrollUpdated) {
        // Correct the display port due to the difference between mScrollOffset and the
        // actual scroll offset.
        AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
    } else {
        // For whatever reason we couldn't update the scroll offset on the scroll frame,
        // which means the data APZ used for its displayport calculation is stale. Fall
        // back to a sane default behaviour. Note that we don't tile-align the recentered
        // displayport because tile-alignment depends on the scroll position, and the
        // scroll position here is out of our control. See bug 966507 comment 21 for a
        // more detailed explanation.
        RecenterDisplayPort(aMetrics);
    }

    aMetrics.SetScrollOffset(actualScrollOffset);

    // The mZoom variable on the frame metrics stores the CSS-to-screen scale for this
    // frame. This scale includes all of the (cumulative) resolutions set on the presShells
    // from the root down to this frame. However, when setting the resolution, we only
    // want the piece of the resolution that corresponds to this presShell, rather than
    // all of the cumulative stuff, so we need to divide out the parent resolutions.
    // Finally, we multiply by a ScreenToLayerScale of 1.0f because the goal here is to
    // take the async zoom calculated by the APZC and tell gecko about it (turning it into
    // a "sync" zoom) which will update the resolution at which the layer is painted.
    ParentLayerToLayerScale presShellResolution =
        aMetrics.GetZoom()
        / aMetrics.mDevPixelsPerCSSPixel
        / aMetrics.GetParentResolution()
        * ScreenToLayerScale(1.0f);
    aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale);

    // Finally, we set the displayport.
    nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
    if (!content) {
        return;
    }
    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(content);
    if (!element) {
        return;
    }

    gfx::IntSize alignment = gfxPrefs::LayersTilesEnabled()
        ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) :
          gfx::IntSize(0, 0);
    LayerMargin margins = aMetrics.GetDisplayPortMargins();
    aUtils->SetDisplayPortMarginsForElement(margins.left,
                                            margins.top,
                                            margins.right,
                                            margins.bottom,
                                            alignment.width,
                                            alignment.height,
                                            element, 0);
    CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
    nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(),
                baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(),
                baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
                baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
    nsLayoutUtils::SetDisplayPortBaseIfNotSet(content, base);
}