1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef GFX_FRAMEMETRICS_H
8 #define GFX_FRAMEMETRICS_H
10 #include <stdint.h> // for uint8_t, uint32_t, uint64_t
13 #include "Units.h" // for CSSRect, CSSPixel, etc
14 #include "UnitTransforms.h" // for ViewAs
15 #include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
16 #include "mozilla/HashFunctions.h" // for HashGeneric
17 #include "mozilla/Maybe.h"
18 #include "mozilla/gfx/BasePoint.h" // for BasePoint
19 #include "mozilla/gfx/Rect.h" // for RoundedIn
20 #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
21 #include "mozilla/gfx/Logging.h" // for Log
22 #include "mozilla/layers/LayersTypes.h" // for ScrollDirection
23 #include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
24 #include "mozilla/ScrollPositionUpdate.h" // for ScrollPositionUpdate
25 #include "mozilla/ScrollSnapInfo.h"
26 #include "mozilla/ScrollSnapTargetId.h"
27 #include "mozilla/StaticPtr.h" // for StaticAutoPtr
28 #include "mozilla/TimeStamp.h" // for TimeStamp
29 #include "nsTHashMap.h" // for nsTHashMap
31 #include "PLDHashTable.h" // for PLDHashNumber
33 struct nsStyleDisplay
;
35 enum class StyleOverscrollBehavior
: uint8_t;
36 } // namespace mozilla
47 * Metrics about a scroll frame that are sent to the compositor and used
50 * This is used for two main purposes:
52 * (1) Sending information about a scroll frame to the compositor and APZ
53 * as part of a layers or WebRender transaction.
54 * (2) Storing information about a scroll frame in APZ that persists
55 * between transactions.
57 * TODO: Separate these two uses into two distinct structures.
59 * A related class, RepaintRequest, is used for sending information about a
60 * scroll frame back from the compositor to the main thread when requesting
61 * a repaint of the scroll frame's contents.
64 friend struct IPC::ParamTraits
<mozilla::layers::FrameMetrics
>;
65 friend std::ostream
& operator<<(std::ostream
& aStream
,
66 const FrameMetrics
& aMetrics
);
68 typedef ScrollableLayerGuid::ViewID ViewID
;
72 MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(
73 ScrollOffsetUpdateType
, uint8_t, (
74 eNone
, // The default; the scroll offset was not updated
75 eMainThread
, // The scroll offset was updated by the main thread.
76 eRestore
// The scroll offset was updated by the main thread, but
77 // as a restore from history or after a frame
78 // reconstruction. In this case, APZ can ignore the
79 // offset change if the user has done an APZ scroll
85 : mScrollId(ScrollableLayerGuid::NULL_SCROLL_ID
),
86 mPresShellResolution(1),
87 mCompositionBounds(0, 0, 0, 0),
88 mCompositionBoundsWidthIgnoringScrollbars(0),
89 mDisplayPort(0, 0, 0, 0),
90 mScrollableRect(0, 0, 0, 0),
91 mDevPixelsPerCSSPixel(1),
93 mBoundingCompositionSize(0, 0),
95 mLayoutViewport(0, 0, 0, 0),
96 mVisualDestination(0, 0),
97 mVisualScrollUpdateType(eNone
),
98 mIsRootContent(false),
99 mIsScrollInfoLayer(false),
100 mHasNonZeroDisplayPortMargins(false),
101 mMinimalDisplayPort(false) {}
103 // Default copy ctor and operator= are fine
105 bool operator==(const FrameMetrics
& aOther
) const {
106 // Put mScrollId at the top since it's the most likely one to fail.
107 return mScrollId
== aOther
.mScrollId
&&
108 mPresShellResolution
== aOther
.mPresShellResolution
&&
109 mCompositionBounds
.IsEqualEdges(aOther
.mCompositionBounds
) &&
110 mCompositionBoundsWidthIgnoringScrollbars
==
111 aOther
.mCompositionBoundsWidthIgnoringScrollbars
&&
112 mDisplayPort
.IsEqualEdges(aOther
.mDisplayPort
) &&
113 mScrollableRect
.IsEqualEdges(aOther
.mScrollableRect
) &&
114 mCumulativeResolution
== aOther
.mCumulativeResolution
&&
115 mDevPixelsPerCSSPixel
== aOther
.mDevPixelsPerCSSPixel
&&
116 mScrollOffset
== aOther
.mScrollOffset
&&
117 // don't compare mZoom
118 mScrollGeneration
== aOther
.mScrollGeneration
&&
119 mBoundingCompositionSize
== aOther
.mBoundingCompositionSize
&&
120 mPresShellId
== aOther
.mPresShellId
&&
121 mLayoutViewport
.IsEqualEdges(aOther
.mLayoutViewport
) &&
122 mTransformToAncestorScale
== aOther
.mTransformToAncestorScale
&&
123 mPaintRequestTime
== aOther
.mPaintRequestTime
&&
124 mVisualDestination
== aOther
.mVisualDestination
&&
125 mVisualScrollUpdateType
== aOther
.mVisualScrollUpdateType
&&
126 mIsRootContent
== aOther
.mIsRootContent
&&
127 mIsScrollInfoLayer
== aOther
.mIsScrollInfoLayer
&&
128 mHasNonZeroDisplayPortMargins
==
129 aOther
.mHasNonZeroDisplayPortMargins
&&
130 mMinimalDisplayPort
== aOther
.mMinimalDisplayPort
&&
131 mFixedLayerMargins
== aOther
.mFixedLayerMargins
&&
132 mCompositionSizeWithoutDynamicToolbar
==
133 aOther
.mCompositionSizeWithoutDynamicToolbar
;
136 bool operator!=(const FrameMetrics
& aOther
) const {
137 return !operator==(aOther
);
140 bool IsScrollable() const {
141 return mScrollId
!= ScrollableLayerGuid::NULL_SCROLL_ID
;
144 CSSToScreenScale2D
DisplayportPixelsPerCSSPixel() const {
145 // Note: mZoom includes the async zoom. We want to include the async zoom
146 // even though the size of the pixels of our *current* displayport does not
147 // yet reflect it, because this function is used in the context of a repaint
148 // request where we'll be asking for a *new* displayport which does reflect
149 // the async zoom. Note 2: we include the transform to ancestor scale
150 // because this function (as the name implies) is used only in various
151 // displayport calculation related places, and those calculations want the
152 // transform to ancestor scale to be included becaese they want to reason
153 // about pixels which are the same size as screen pixels (so displayport
154 // sizes are e.g. limited to a multiple of the screen size). Whereas mZoom
155 // and mCumulativeResolution do not include it because of expectations of
156 // the code where they are used.
157 return mZoom
* mTransformToAncestorScale
;
160 CSSToLayerScale
LayersPixelsPerCSSPixel() const {
161 return mDevPixelsPerCSSPixel
* mCumulativeResolution
;
164 // Get the amount by which this frame has been zoomed since the last repaint.
165 LayerToParentLayerScale
GetAsyncZoom() const {
166 return mZoom
/ LayersPixelsPerCSSPixel();
169 // Ensure the scrollableRect is at least as big as the compositionBounds
170 // because the scrollableRect can be smaller if the content is not large
171 // and the scrollableRect hasn't been updated yet.
172 // We move the scrollableRect up because we don't know if we can move it
173 // down. i.e. we know that scrollableRect can go back as far as zero.
174 // but we don't know how much further ahead it can go.
175 CSSRect
GetExpandedScrollableRect() const {
176 CSSRect scrollableRect
= mScrollableRect
;
177 CSSSize compSize
= CalculateCompositedSizeInCssPixels();
178 if (scrollableRect
.Width() < compSize
.width
) {
179 scrollableRect
.SetRectX(
180 std::max(0.f
, scrollableRect
.X() -
181 (compSize
.width
- scrollableRect
.Width())),
185 if (scrollableRect
.Height() < compSize
.height
) {
186 scrollableRect
.SetRectY(
187 std::max(0.f
, scrollableRect
.Y() -
188 (compSize
.height
- scrollableRect
.Height())),
192 return scrollableRect
;
195 CSSSize
CalculateCompositedSizeInCssPixels() const {
196 return CalculateCompositedSizeInCssPixels(mCompositionBounds
, mZoom
);
200 * Calculate the composition bounds of this frame in the CSS pixels of
201 * the content surrounding the scroll frame (OuterCSS pixels).
202 * Note that it does not make sense to ask for the composition bounds in the
203 * CSS pixels of the scrolled content (that is, regular CSS pixels),
204 * because the origin of the composition bounds is not meaningful in that
205 * coordinate space. (The size is, use CalculateCompositedSizeInCssPixels()
208 OuterCSSRect
CalculateCompositionBoundsInOuterCssPixels() const {
209 if (GetZoom() == CSSToParentLayerScale(0)) {
210 return OuterCSSRect(); // avoid division by zero
212 // The CSS pixels of the scrolled content and the CSS pixels of the
213 // surrounding content only differ if the scrolled content is rendered
214 // at a higher resolution, and the difference is the resolution.
215 return mCompositionBounds
/ GetZoom() * GetCSSToOuterCSSScale();
218 CSSSize
CalculateBoundedCompositedSizeInCssPixels() const {
219 CSSSize size
= CalculateCompositedSizeInCssPixels();
220 size
.width
= std::min(size
.width
, mBoundingCompositionSize
.width
);
221 size
.height
= std::min(size
.height
, mBoundingCompositionSize
.height
);
225 CSSRect
CalculateScrollRange() const {
226 return CalculateScrollRange(mScrollableRect
, mCompositionBounds
, mZoom
);
229 void ScrollBy(const CSSPoint
& aPoint
) {
230 SetVisualScrollOffset(GetVisualScrollOffset() + aPoint
);
233 void ZoomBy(float aScale
) { mZoom
.scale
*= aScale
; }
236 * Compares an APZ frame metrics with an incoming content frame metrics
237 * to see if APZ has a scroll offset that has not been incorporated into
238 * the content frame metrics.
240 bool HasPendingScroll(const FrameMetrics
& aContentFrameMetrics
) const {
241 return GetVisualScrollOffset() !=
242 aContentFrameMetrics
.GetVisualScrollOffset();
246 * Returns true if the layout scroll offset or visual scroll offset changed.
248 bool ApplyScrollUpdateFrom(const ScrollPositionUpdate
& aUpdate
);
251 * Applies the relative scroll offset update contained in aOther to the
252 * scroll offset contained in this. The scroll delta is clamped to the
255 * @returns The clamped scroll offset delta that was applied
257 CSSPoint
ApplyRelativeScrollUpdateFrom(const ScrollPositionUpdate
& aUpdate
);
259 CSSPoint
ApplyPureRelativeScrollUpdateFrom(
260 const ScrollPositionUpdate
& aUpdate
);
262 void UpdatePendingScrollInfo(const ScrollPositionUpdate
& aInfo
);
265 void SetPresShellResolution(float aPresShellResolution
) {
266 mPresShellResolution
= aPresShellResolution
;
269 float GetPresShellResolution() const { return mPresShellResolution
; }
271 void SetCompositionBounds(const ParentLayerRect
& aCompositionBounds
) {
272 mCompositionBounds
= aCompositionBounds
;
275 const ParentLayerRect
& GetCompositionBounds() const {
276 return mCompositionBounds
;
279 void SetCompositionBoundsWidthIgnoringScrollbars(
280 const ParentLayerCoord aCompositionBoundsWidthIgnoringScrollbars
) {
281 mCompositionBoundsWidthIgnoringScrollbars
=
282 aCompositionBoundsWidthIgnoringScrollbars
;
285 const ParentLayerCoord
GetCompositionBoundsWidthIgnoringScrollbars() const {
286 return mCompositionBoundsWidthIgnoringScrollbars
;
289 void SetDisplayPort(const CSSRect
& aDisplayPort
) {
290 mDisplayPort
= aDisplayPort
;
293 const CSSRect
& GetDisplayPort() const { return mDisplayPort
; }
295 void SetCumulativeResolution(
296 const LayoutDeviceToLayerScale
& aCumulativeResolution
) {
297 mCumulativeResolution
= aCumulativeResolution
;
300 const LayoutDeviceToLayerScale
& GetCumulativeResolution() const {
301 return mCumulativeResolution
;
304 void SetDevPixelsPerCSSPixel(
305 const CSSToLayoutDeviceScale
& aDevPixelsPerCSSPixel
) {
306 mDevPixelsPerCSSPixel
= aDevPixelsPerCSSPixel
;
309 const CSSToLayoutDeviceScale
& GetDevPixelsPerCSSPixel() const {
310 return mDevPixelsPerCSSPixel
;
313 CSSToOuterCSSScale
GetCSSToOuterCSSScale() const {
314 // The scale difference between CSS and OuterCSS pixels is the
315 // part of the zoom that's not subject to all enclosing content,
316 // i.e. the pres shell resolution.
317 return CSSToOuterCSSScale(mPresShellResolution
);
320 void SetIsRootContent(bool aIsRootContent
) {
321 mIsRootContent
= aIsRootContent
;
324 bool IsRootContent() const { return mIsRootContent
; }
326 // Set scroll offset, first clamping to the scroll range.
327 // Return true if it changed.
328 bool ClampAndSetVisualScrollOffset(const CSSPoint
& aScrollOffset
) {
329 CSSPoint offsetBefore
= GetVisualScrollOffset();
330 SetVisualScrollOffset(CalculateScrollRange().ClampPoint(aScrollOffset
));
331 return (offsetBefore
!= GetVisualScrollOffset());
334 CSSPoint
GetLayoutScrollOffset() const { return mLayoutViewport
.TopLeft(); }
335 // Returns true if it changed.
336 bool SetLayoutScrollOffset(const CSSPoint
& aLayoutScrollOffset
) {
337 CSSPoint offsetBefore
= GetLayoutScrollOffset();
338 mLayoutViewport
.MoveTo(aLayoutScrollOffset
);
339 return (offsetBefore
!= GetLayoutScrollOffset());
342 const CSSPoint
& GetVisualScrollOffset() const { return mScrollOffset
; }
343 void SetVisualScrollOffset(const CSSPoint
& aVisualScrollOffset
) {
344 mScrollOffset
= aVisualScrollOffset
;
347 void SetZoom(const CSSToParentLayerScale
& aZoom
) { mZoom
= aZoom
; }
349 const CSSToParentLayerScale
& GetZoom() const { return mZoom
; }
351 void SetScrollGeneration(
352 const MainThreadScrollGeneration
& aScrollGeneration
) {
353 mScrollGeneration
= aScrollGeneration
;
356 MainThreadScrollGeneration
GetScrollGeneration() const {
357 return mScrollGeneration
;
360 ViewID
GetScrollId() const { return mScrollId
; }
362 void SetScrollId(ViewID scrollId
) { mScrollId
= scrollId
; }
364 void SetBoundingCompositionSize(const CSSSize
& aBoundingCompositionSize
) {
365 mBoundingCompositionSize
= aBoundingCompositionSize
;
368 const CSSSize
& GetBoundingCompositionSize() const {
369 return mBoundingCompositionSize
;
372 uint32_t GetPresShellId() const { return mPresShellId
; }
374 void SetPresShellId(uint32_t aPresShellId
) { mPresShellId
= aPresShellId
; }
376 void SetLayoutViewport(const CSSRect
& aLayoutViewport
) {
377 mLayoutViewport
= aLayoutViewport
;
380 const CSSRect
& GetLayoutViewport() const { return mLayoutViewport
; }
382 CSSRect
GetVisualViewport() const {
383 return CSSRect(GetVisualScrollOffset(),
384 CalculateCompositedSizeInCssPixels());
387 void SetTransformToAncestorScale(
388 const ParentLayerToScreenScale2D
& aTransformToAncestorScale
) {
389 mTransformToAncestorScale
= aTransformToAncestorScale
;
392 const ParentLayerToScreenScale2D
& GetTransformToAncestorScale() const {
393 return mTransformToAncestorScale
;
396 const CSSRect
& GetScrollableRect() const { return mScrollableRect
; }
398 void SetScrollableRect(const CSSRect
& aScrollableRect
) {
399 mScrollableRect
= aScrollableRect
;
402 // If the frame is in vertical-RTL writing mode(E.g. "writing-mode:
403 // vertical-rl" in CSS), or if it's in horizontal-RTL writing-mode(E.g.
404 // "writing-mode: horizontal-tb; direction: rtl;" in CSS), then this function
405 // returns true. From the representation perspective, frames whose horizontal
406 // contents start at rightside also cause their horizontal scrollbars, if any,
407 // initially start at rightside. So we can also learn about the initial side
408 // of the horizontal scrollbar for the frame by calling this function.
409 bool IsHorizontalContentRightToLeft() const { return mScrollableRect
.x
< 0; }
411 void SetPaintRequestTime(const TimeStamp
& aTime
) {
412 mPaintRequestTime
= aTime
;
414 const TimeStamp
& GetPaintRequestTime() const { return mPaintRequestTime
; }
416 void SetIsScrollInfoLayer(bool aIsScrollInfoLayer
) {
417 mIsScrollInfoLayer
= aIsScrollInfoLayer
;
419 bool IsScrollInfoLayer() const { return mIsScrollInfoLayer
; }
421 void SetHasNonZeroDisplayPortMargins(bool aHasNonZeroDisplayPortMargins
) {
422 mHasNonZeroDisplayPortMargins
= aHasNonZeroDisplayPortMargins
;
424 bool HasNonZeroDisplayPortMargins() const {
425 return mHasNonZeroDisplayPortMargins
;
428 void SetMinimalDisplayPort(bool aMinimalDisplayPort
) {
429 mMinimalDisplayPort
= aMinimalDisplayPort
;
431 bool IsMinimalDisplayPort() const { return mMinimalDisplayPort
; }
433 void SetVisualDestination(const CSSPoint
& aVisualDestination
) {
434 mVisualDestination
= aVisualDestination
;
436 const CSSPoint
& GetVisualDestination() const { return mVisualDestination
; }
438 void SetVisualScrollUpdateType(ScrollOffsetUpdateType aUpdateType
) {
439 mVisualScrollUpdateType
= aUpdateType
;
441 ScrollOffsetUpdateType
GetVisualScrollUpdateType() const {
442 return mVisualScrollUpdateType
;
445 // Determine if the visual viewport is outside of the layout viewport and
446 // adjust the x,y-offset in mLayoutViewport accordingly. This is necessary to
447 // allow APZ to async-scroll the layout viewport.
449 // This is a no-op if mIsRootContent is false.
450 void RecalculateLayoutViewportOffset();
452 void SetFixedLayerMargins(const ScreenMargin
& aFixedLayerMargins
) {
453 mFixedLayerMargins
= aFixedLayerMargins
;
455 const ScreenMargin
& GetFixedLayerMargins() const {
456 return mFixedLayerMargins
;
459 void SetCompositionSizeWithoutDynamicToolbar(const ParentLayerSize
& aSize
) {
460 MOZ_ASSERT(mIsRootContent
);
461 mCompositionSizeWithoutDynamicToolbar
= aSize
;
463 const ParentLayerSize
& GetCompositionSizeWithoutDynamicToolbar() const {
464 MOZ_ASSERT(mIsRootContent
);
465 return mCompositionSizeWithoutDynamicToolbar
;
468 // Helper function for RecalculateViewportOffset(). Exposed so that
469 // APZC can perform the operation on other copies of the layout
470 // and visual viewport rects (e.g. the "effective" ones used to implement
472 // Modifies |aLayoutViewport| to continue enclosing |aVisualViewport|
474 // The layout viewport needs to remain clamped to the scrollable rect,
475 // and we pass in the scrollable rect so this function can maintain that
477 static void KeepLayoutViewportEnclosingVisualViewport(
478 const CSSRect
& aVisualViewport
, const CSSRect
& aScrollableRect
,
479 CSSRect
& aLayoutViewport
);
481 // Helper functions exposed so we can perform operations on copies outside of
482 // frame metrics object.
483 static CSSRect
CalculateScrollRange(const CSSRect
& aScrollableRect
,
484 const ParentLayerRect
& aCompositionBounds
,
485 const CSSToParentLayerScale
& aZoom
);
486 static CSSSize
CalculateCompositedSizeInCssPixels(
487 const ParentLayerRect
& aCompositionBounds
,
488 const CSSToParentLayerScale
& aZoom
);
491 // A ID assigned to each scrollable frame, unique within each LayersId..
494 // The pres-shell resolution that has been induced on the document containing
495 // this scroll frame as a result of zooming this scroll frame (whether via
496 // user action, or choosing an initial zoom level on page load). This can
497 // only be different from 1.0 for frames that are zoomable, which currently
498 // is just the root content document's root scroll frame
499 // (mIsRootContent = true).
500 // This is a plain float rather than a ScaleFactor because in and of itself
501 // it does not convert between any coordinate spaces for which we have names.
502 float mPresShellResolution
;
504 // This is the area within the widget that we're compositing to. It is in the
505 // layer coordinates of the scrollable content's parent layer.
507 // The size of the composition bounds corresponds to the size of the scroll
508 // frame's scroll port (but in a coordinate system where the size does not
509 // change during zooming).
511 // The origin of the composition bounds is relative to the scroll node origin.
512 // (The "scroll node origin" is the point such that applying the APZC's
513 // apzc-to-screen transform to it takes you to the window origin, which is
514 // what Screen event coordinates are relative to. In layout terms, it's
515 // the origin of the reference frame passed to ComputeScrollMetadata().)
516 // Unlike the scroll port's origin, it does not change during scrolling of
517 // the scrollable layer to which it is associated. However, it may change due
518 // to scrolling of ancestor layers.
520 // This value is provided by Gecko at layout/paint time.
521 ParentLayerRect mCompositionBounds
;
523 // For RCD-RSF this is the width of the composition bounds ignoring
524 // scrollbars. For everything else this will be the same as the width of the
525 // composition bounds. Only needed for the "resolution changed" check in
526 // NotifyLayersUpdated, once that switches to using IsResolutionUpdated we can
528 ParentLayerCoord mCompositionBoundsWidthIgnoringScrollbars
;
530 // The area of a scroll frame's contents that has been painted, relative to
531 // GetLayoutScrollOffset().
533 // Should not be larger than GetExpandedScrollableRect().
535 // To pre-render a margin of 100 CSS pixels around the scroll port,
536 // { x = -100, y = - 100,
537 // width = scrollPort.width + 200, height = scrollPort.height + 200 }
538 // where scrollPort = CalculateCompositedSizeInCssPixels().
539 CSSRect mDisplayPort
;
541 // The scrollable bounds of a frame. This is determined by reflow.
542 // Ordinarily the x and y will be 0 and the width and height will be the
543 // size of the element being scrolled. However for RTL pages or elements
544 // the x value may be negative.
546 // For scrollable frames that are overflow:hidden the x and y are usually
547 // set to the value of the current scroll offset, and the width and height
548 // will match the composition bounds width and height. In effect this reduces
549 // the scrollable range to 0.
551 // This is in the same coordinate space as |mScrollOffset|, but a different
552 // coordinate space than |mDisplayPort|. Note also that this coordinate
553 // system is understood by window.scrollTo().
554 CSSRect mScrollableRect
;
556 // The cumulative resolution of the current frame. This is the product of the
557 // pres-shell resolutions of the document containing this scroll frame and its
558 // in-process ancestors. This information is provided by Gecko at layout/paint
559 // time. Notably, for out of process iframes cumulative resolution will be 1.
560 // The reason for this is that AsyncPanZoomController::GetTransformToThis does
561 // not contain the resolution in the process of the root content document, but
562 // in oop iframes AsyncPanZoomController::GetTransformToThis does contain the
563 // resolution. This makes coordinate math work out in APZ code because in the
564 // old layers backend GetTransformToThis was a transform of rendered pixels,
565 // and the pixels were rendered with the scale applied already. The reason
566 // that AsyncPanZoomController::GetTransformToThis contains the scale in oop
567 // iframes is because we include the resolution in the transform that includes
568 // the iframe via this call
569 // https://searchfox.org/mozilla-central/rev/2eebd6e256fa0355e08421265e57ee1307836d92/layout/generic/nsSubDocumentFrame.cpp#1404
570 // So when coordinates are passed to the process of the oop iframe they have
571 // the resolution removed by unapplying that transform which includes the
573 LayoutDeviceToLayerScale mCumulativeResolution
;
575 // The conversion factor between CSS pixels and device pixels for this frame.
576 // This can vary based on a variety of things, such as reflowing-zoom.
577 CSSToLayoutDeviceScale mDevPixelsPerCSSPixel
;
579 // The position of the top-left of the scroll frame's scroll port, relative
580 // to the scrollable content's origin.
582 // This is in the same coordinate space as |mScrollableRect|, but a different
583 // coordinate space than |mDisplayPort|.
585 // It is required that the rect:
586 // { x = mScrollOffset.x, y = mScrollOffset.y,
587 // width = scrollPort.width,
588 // height = scrollPort.height }
589 // (where scrollPort = CalculateCompositedSizeInCssPixels())
590 // be within |mScrollableRect|.
591 CSSPoint mScrollOffset
;
593 // The "user zoom". Content is painted by gecko at mCumulativeResolution *
594 // mDevPixelsPerCSSPixel, but will be drawn to the screen at mZoom. In the
595 // steady state, the two will be the same, but during an async zoom action the
596 // two may diverge. This information is initialized in Gecko but updated in
598 CSSToParentLayerScale mZoom
;
600 // The scroll generation counter used to acknowledge the scroll offset update.
601 MainThreadScrollGeneration mScrollGeneration
;
603 // A bounding size for our composition bounds (no larger than the
604 // cross-process RCD-RSF's composition size), in local CSS pixels.
605 CSSSize mBoundingCompositionSize
;
607 uint32_t mPresShellId
;
609 // For a root scroll frame (RSF), the document's layout viewport
610 // (sometimes called "CSS viewport" in older code).
612 // Its size is the dimensions we're using to constrain the <html> element
613 // of the document (i.e. the initial containing block (ICB) size).
615 // Its origin is the RSF's layout scroll position, i.e. the scroll position
616 // exposed to web content via window.scrollX/Y.
618 // Note that only the root content document's RSF has a layout viewport
619 // that's distinct from the visual viewport. For an iframe RSF, the two
622 // For a scroll frame that is not an RSF, this metric is meaningless and
624 CSSRect mLayoutViewport
;
626 // The scale induced by css transforms and presshell resolution in this
627 // process and any ancestor processes that encloses this scroll frame that is
628 // _not_ included in mCumulativeResolution. This means that in the process of
629 // the root content document this only includes css transform scale (which
630 // happens in that process, but we assume there can be no css transform scale
631 // above the root content document). In other processes it includes css
632 // transform scale and any resolution scale in the current process and all
633 // ancestor processes.
634 ParentLayerToScreenScale2D mTransformToAncestorScale
;
636 // The time at which the APZC last requested a repaint for this scroll frame.
637 TimeStamp mPaintRequestTime
;
639 // These fields are used when the main thread wants to set a visual viewport
640 // offset that's distinct from the layout viewport offset.
641 // In this case, mVisualScrollUpdateType is set to eMainThread, and
642 // mVisualDestination is set to desired visual destination (relative
643 // to the document, like mScrollOffset).
644 CSSPoint mVisualDestination
;
645 ScrollOffsetUpdateType mVisualScrollUpdateType
;
647 // 'fixed layer margins' on the main-thread. This is only used for the
648 // root-content scroll frame.
649 ScreenMargin mFixedLayerMargins
;
651 // Similar to mCompositionBounds.Size() but not including the dynamic toolbar
653 // If we are not using a dynamic toolbar, this has the same value as
654 // mCompositionBounds.Size().
655 ParentLayerSize mCompositionSizeWithoutDynamicToolbar
;
657 // Whether or not this is the root scroll frame for the root content document.
658 bool mIsRootContent
: 1;
660 // True if this scroll frame is a scroll info layer. A scroll info layer is
661 // not layerized and its content cannot be truly async-scrolled, but its
662 // metrics are still sent to and updated by the compositor, with the updates
663 // being reflected on the next paint rather than the next composite.
664 bool mIsScrollInfoLayer
: 1;
666 // Whether there are non-zero display port margins set on this element.
667 bool mHasNonZeroDisplayPortMargins
: 1;
669 // Whether this scroll frame is using a minimal display port, which means that
670 // any set display port margins are ignored when calculating the display port
671 // and instead zero margins are used and further no tile or alignment
672 // boundaries are used that could potentially expand the size.
673 bool mMinimalDisplayPort
: 1;
677 // When adding a new field:
679 // - First, consider whether the field can be added to ScrollMetadata
680 // instead. If so, prefer that.
682 // - Otherwise, the following places should be updated to include them
684 // FrameMetrics::operator ==
685 // AsyncPanZoomController::NotifyLayersUpdated
686 // The ParamTraits specialization in LayersMessageUtils.h
688 // Please add new fields above this comment.
692 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
693 OverscrollBehavior
, uint8_t, (
700 std::ostream
& operator<<(std::ostream
& aStream
,
701 const OverscrollBehavior
& aBehavior
);
703 struct OverscrollBehaviorInfo final
{
704 OverscrollBehaviorInfo();
706 // Construct from StyleOverscrollBehavior values.
707 static OverscrollBehaviorInfo
FromStyleConstants(
708 StyleOverscrollBehavior aBehaviorX
, StyleOverscrollBehavior aBehaviorY
);
710 bool operator==(const OverscrollBehaviorInfo
& aOther
) const;
711 friend std::ostream
& operator<<(std::ostream
& aStream
,
712 const OverscrollBehaviorInfo
& aInfo
);
714 auto MutTiedFields() { return std::tie(mBehaviorX
, mBehaviorY
); }
716 OverscrollBehavior mBehaviorX
;
717 OverscrollBehavior mBehaviorY
;
721 * Metadata about a scroll frame that's sent to the compositor during a layers
722 * or WebRender transaction, and also stored by APZ between transactions.
723 * This includes the scroll frame's FrameMetrics, as well as other metadata.
724 * We don't put the other metadata into FrameMetrics to avoid FrameMetrics
725 * becoming too bloated (as a FrameMetrics is e.g. stored in memory shared
726 * with the content process).
728 struct ScrollMetadata
{
729 friend struct IPC::ParamTraits
<mozilla::layers::ScrollMetadata
>;
730 friend std::ostream
& operator<<(std::ostream
& aStream
,
731 const ScrollMetadata
& aMetadata
);
733 typedef ScrollableLayerGuid::ViewID ViewID
;
736 static StaticAutoPtr
<const ScrollMetadata
>
737 sNullMetadata
; // We sometimes need an empty metadata
740 : mScrollParentId(ScrollableLayerGuid::NULL_SCROLL_ID
),
741 mLineScrollAmount(0, 0),
742 mPageScrollAmount(0, 0),
743 mHasScrollgrab(false),
744 mIsLayersIdRoot(false),
745 mIsAutoDirRootContentRTL(false),
746 mForceDisableApz(false),
747 mResolutionUpdated(false),
748 mIsRDMTouchSimulationActive(false),
749 mDidContentGetPainted(true),
750 mForceMousewheelAutodir(false),
751 mForceMousewheelAutodirHonourRoot(false),
752 mIsPaginatedPresentation(false) {}
754 bool operator==(const ScrollMetadata
& aOther
) const {
755 return mMetrics
== aOther
.mMetrics
&& mSnapInfo
== aOther
.mSnapInfo
&&
756 mScrollParentId
== aOther
.mScrollParentId
&&
757 // don't compare mContentDescription
758 mLineScrollAmount
== aOther
.mLineScrollAmount
&&
759 mPageScrollAmount
== aOther
.mPageScrollAmount
&&
760 mHasScrollgrab
== aOther
.mHasScrollgrab
&&
761 mIsLayersIdRoot
== aOther
.mIsLayersIdRoot
&&
762 mIsAutoDirRootContentRTL
== aOther
.mIsAutoDirRootContentRTL
&&
763 mForceDisableApz
== aOther
.mForceDisableApz
&&
764 mResolutionUpdated
== aOther
.mResolutionUpdated
&&
765 mIsRDMTouchSimulationActive
== aOther
.mIsRDMTouchSimulationActive
&&
766 mDidContentGetPainted
== aOther
.mDidContentGetPainted
&&
767 mForceMousewheelAutodir
== aOther
.mForceMousewheelAutodir
&&
768 mForceMousewheelAutodirHonourRoot
==
769 aOther
.mForceMousewheelAutodirHonourRoot
&&
770 mIsPaginatedPresentation
== aOther
.mIsPaginatedPresentation
&&
771 mDisregardedDirection
== aOther
.mDisregardedDirection
&&
772 mOverscrollBehavior
== aOther
.mOverscrollBehavior
&&
773 mScrollUpdates
== aOther
.mScrollUpdates
;
776 bool operator!=(const ScrollMetadata
& aOther
) const {
777 return !operator==(aOther
);
780 bool IsDefault() const {
783 def
.mMetrics
.SetPresShellId(mMetrics
.GetPresShellId());
784 return (def
== *this);
787 FrameMetrics
& GetMetrics() { return mMetrics
; }
788 const FrameMetrics
& GetMetrics() const { return mMetrics
; }
790 void SetSnapInfo(ScrollSnapInfo
&& aSnapInfo
) {
791 mSnapInfo
= std::move(aSnapInfo
);
793 const ScrollSnapInfo
& GetSnapInfo() const { return mSnapInfo
; }
795 ViewID
GetScrollParentId() const { return mScrollParentId
; }
797 void SetScrollParentId(ViewID aParentId
) { mScrollParentId
= aParentId
; }
798 const nsCString
& GetContentDescription() const { return mContentDescription
; }
799 void SetContentDescription(const nsCString
& aContentDescription
) {
800 mContentDescription
= aContentDescription
;
802 const LayoutDeviceIntSize
& GetLineScrollAmount() const {
803 return mLineScrollAmount
;
805 void SetLineScrollAmount(const LayoutDeviceIntSize
& size
) {
806 mLineScrollAmount
= size
;
808 const LayoutDeviceIntSize
& GetPageScrollAmount() const {
809 return mPageScrollAmount
;
811 void SetPageScrollAmount(const LayoutDeviceIntSize
& size
) {
812 mPageScrollAmount
= size
;
814 void SetHasScrollgrab(bool aHasScrollgrab
) {
815 mHasScrollgrab
= aHasScrollgrab
;
817 bool GetHasScrollgrab() const { return mHasScrollgrab
; }
818 void SetIsLayersIdRoot(bool aValue
) { mIsLayersIdRoot
= aValue
; }
819 bool IsLayersIdRoot() const { return mIsLayersIdRoot
; }
820 void SetIsAutoDirRootContentRTL(bool aValue
) {
821 mIsAutoDirRootContentRTL
= aValue
;
823 bool IsAutoDirRootContentRTL() const { return mIsAutoDirRootContentRTL
; }
824 void SetForceDisableApz(bool aForceDisable
) {
825 mForceDisableApz
= aForceDisable
;
827 bool IsApzForceDisabled() const { return mForceDisableApz
; }
828 void SetResolutionUpdated(bool aUpdated
) { mResolutionUpdated
= aUpdated
; }
829 bool IsResolutionUpdated() const { return mResolutionUpdated
; }
831 void SetIsRDMTouchSimulationActive(bool aValue
) {
832 mIsRDMTouchSimulationActive
= aValue
;
834 bool GetIsRDMTouchSimulationActive() const {
835 return mIsRDMTouchSimulationActive
;
838 void SetForceMousewheelAutodir(bool aValue
) {
839 mForceMousewheelAutodir
= aValue
;
841 bool ForceMousewheelAutodir() const { return mForceMousewheelAutodir
; }
843 void SetForceMousewheelAutodirHonourRoot(bool aValue
) {
844 mForceMousewheelAutodirHonourRoot
= aValue
;
846 bool ForceMousewheelAutodirHonourRoot() const {
847 return mForceMousewheelAutodirHonourRoot
;
850 void SetIsPaginatedPresentation(bool aValue
) {
851 mIsPaginatedPresentation
= aValue
;
853 bool IsPaginatedPresentation() const { return mIsPaginatedPresentation
; }
855 bool DidContentGetPainted() const { return mDidContentGetPainted
; }
858 // For use in IPC only
859 void SetDidContentGetPainted(bool aValue
) { mDidContentGetPainted
= aValue
; }
862 // For more details about the concept of a disregarded direction, refer to the
863 // code which defines mDisregardedDirection.
864 Maybe
<ScrollDirection
> GetDisregardedDirection() const {
865 return mDisregardedDirection
;
867 void SetDisregardedDirection(const Maybe
<ScrollDirection
>& aValue
) {
868 mDisregardedDirection
= aValue
;
871 void SetOverscrollBehavior(
872 const OverscrollBehaviorInfo
& aOverscrollBehavior
) {
873 mOverscrollBehavior
= aOverscrollBehavior
;
875 const OverscrollBehaviorInfo
& GetOverscrollBehavior() const {
876 return mOverscrollBehavior
;
879 void SetScrollUpdates(const nsTArray
<ScrollPositionUpdate
>& aUpdates
) {
880 mScrollUpdates
= aUpdates
;
883 const nsTArray
<ScrollPositionUpdate
>& GetScrollUpdates() const {
884 return mScrollUpdates
;
887 void UpdatePendingScrollInfo(nsTArray
<ScrollPositionUpdate
>&& aUpdates
) {
888 MOZ_ASSERT(!aUpdates
.IsEmpty());
889 mMetrics
.UpdatePendingScrollInfo(aUpdates
.LastElement());
891 mDidContentGetPainted
= false;
892 mScrollUpdates
.Clear();
893 mScrollUpdates
.AppendElements(std::move(aUpdates
));
896 void PrependUpdates(const nsTArray
<ScrollPositionUpdate
>& aUpdates
) {
897 MOZ_ASSERT(!aUpdates
.IsEmpty());
899 mScrollUpdates
.InsertElementsAt(0, aUpdates
);
903 FrameMetrics mMetrics
;
905 // Information used to determine where to snap to for a given scroll.
906 ScrollSnapInfo mSnapInfo
;
908 // The ViewID of the scrollable frame to which overscroll should be handed
910 ViewID mScrollParentId
;
912 // A description of the content element corresponding to this frame.
913 // This is empty unless this is a scrollable layer and the
914 // apz.printtree pref is turned on.
915 nsCString mContentDescription
;
917 // The value of GetLineScrollAmount(), for scroll frames.
918 LayoutDeviceIntSize mLineScrollAmount
;
920 // The value of GetPageScrollAmount(), for scroll frames.
921 LayoutDeviceIntSize mPageScrollAmount
;
923 // Whether or not this frame is for an element marked 'scrollgrab'.
924 bool mHasScrollgrab
: 1;
926 // Whether these framemetrics are for the root scroll frame (root element if
927 // we don't have a root scroll frame) for its layers id.
928 bool mIsLayersIdRoot
: 1;
930 // The AutoDirRootContent is the <body> element in an HTML document, or the
931 // root scrollframe if there is no body. This member variable indicates
932 // whether this element's content in the horizontal direction starts from
933 // right to left (e.g. it's true either if "writing-mode: vertical-rl", or
934 // "writing-mode: horizontal-tb; direction: rtl" in CSS).
935 // When we do auto-dir scrolling (@see mozilla::WheelDeltaAdjustmentStrategy
936 // or refer to bug 1358017 for details), setting a pref can make the code use
937 // the writing mode of this root element instead of the target scrollframe,
938 // and so we need to know if the writing mode is RTL or not.
939 bool mIsAutoDirRootContentRTL
: 1;
941 // Whether or not the compositor should actually do APZ-scrolling on this
943 bool mForceDisableApz
: 1;
945 // Whether the pres shell resolution stored in mMetrics reflects a change
946 // originated by the main thread.
947 bool mResolutionUpdated
: 1;
949 // Whether or not RDM and touch simulation are active for this document.
950 // It's important to note that if RDM is active then this field will be
951 // true for the content document but NOT the chrome document containing
952 // the browser UI and RDM controls.
953 bool mIsRDMTouchSimulationActive
: 1;
955 // Whether this metadata is part of a transaction that also repainted the
956 // content (i.e. updated the displaylist or textures). This gets set to false
957 // for "paint-skip" transactions, where the main thread doesn't repaint but
958 // instead requests APZ to update the compositor scroll offset instead. APZ
959 // needs to be able to distinguish these paint-skip transactions so that it
960 // can use the correct transforms.
961 bool mDidContentGetPainted
: 1;
963 // Whether privileged code has requested that autodir behaviour be
964 // enabled for the scroll frame.
965 bool mForceMousewheelAutodir
: 1;
966 bool mForceMousewheelAutodirHonourRoot
: 1;
968 // Whether this content is being displayed in a paginated fashion
969 // such as printing or print preview. In such cases, content that
970 // would normally only generate one display item may generated one
971 // display item per page, and the different instances may be subject
972 // to different transforms, which constrains the assumptions APZ can make.
973 bool mIsPaginatedPresentation
: 1;
975 // The disregarded direction means the direction which is disregarded anyway,
976 // even if the scroll frame overflows in that direction and the direction is
977 // specified as scrollable. This could happen in some scenarios, for instance,
978 // a single-line text control frame should disregard wheel scroll in
979 // its block-flow direction even if it overflows in that direction.
980 Maybe
<ScrollDirection
> mDisregardedDirection
;
982 // The overscroll behavior for this scroll frame.
983 OverscrollBehaviorInfo mOverscrollBehavior
;
985 // The ordered list of scroll position updates for this scroll frame since
986 // the last transaction.
987 CopyableTArray
<ScrollPositionUpdate
> mScrollUpdates
;
991 // When adding new fields to ScrollMetadata, the following places should be
992 // updated to include them (as needed):
993 // 1. ScrollMetadata::operator ==
994 // 2. AsyncPanZoomController::NotifyLayersUpdated
995 // 3. The ParamTraits specialization in LayersMessageUtils.h
997 // Please add new fields above this comment.
1000 typedef nsTHashMap
<ScrollableLayerGuid::ViewIDHashKey
,
1001 nsTArray
<ScrollPositionUpdate
>>
1004 } // namespace layers
1005 } // namespace mozilla
1007 #endif /* GFX_FRAMEMETRICS_H */