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/dom/InteractiveWidget.h"
19 #include "mozilla/gfx/BasePoint.h" // for BasePoint
20 #include "mozilla/gfx/Rect.h" // for RoundedIn
21 #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
22 #include "mozilla/gfx/Logging.h" // for Log
23 #include "mozilla/layers/LayersTypes.h" // for ScrollDirection
24 #include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
25 #include "mozilla/ScrollPositionUpdate.h" // for ScrollPositionUpdate
26 #include "mozilla/ScrollSnapInfo.h"
27 #include "mozilla/ScrollSnapTargetId.h"
28 #include "mozilla/StaticPtr.h" // for StaticAutoPtr
29 #include "mozilla/TimeStamp.h" // for TimeStamp
30 #include "nsTHashMap.h" // for nsTHashMap
32 #include "PLDHashTable.h" // for PLDHashNumber
34 struct nsStyleDisplay
;
36 enum class StyleOverscrollBehavior
: uint8_t;
37 } // namespace mozilla
48 * Metrics about a scroll frame that are sent to the compositor and used
51 * This is used for two main purposes:
53 * (1) Sending information about a scroll frame to the compositor and APZ
54 * as part of a layers or WebRender transaction.
55 * (2) Storing information about a scroll frame in APZ that persists
56 * between transactions.
58 * TODO: Separate these two uses into two distinct structures.
60 * A related class, RepaintRequest, is used for sending information about a
61 * scroll frame back from the compositor to the main thread when requesting
62 * a repaint of the scroll frame's contents.
65 friend struct IPC::ParamTraits
<mozilla::layers::FrameMetrics
>;
66 friend std::ostream
& operator<<(std::ostream
& aStream
,
67 const FrameMetrics
& aMetrics
);
69 typedef ScrollableLayerGuid::ViewID ViewID
;
73 MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(
74 ScrollOffsetUpdateType
, uint8_t, (
75 eNone
, // The default; the scroll offset was not updated
76 eMainThread
, // The scroll offset was updated by the main thread.
77 eRestore
// The scroll offset was updated by the main thread, but
78 // as a restore from history or after a frame
79 // reconstruction. In this case, APZ can ignore the
80 // offset change if the user has done an APZ scroll
86 : mScrollId(ScrollableLayerGuid::NULL_SCROLL_ID
),
87 mPresShellResolution(1),
88 mCompositionBounds(0, 0, 0, 0),
89 mCompositionBoundsWidthIgnoringScrollbars(0),
90 mDisplayPort(0, 0, 0, 0),
91 mScrollableRect(0, 0, 0, 0),
92 mDevPixelsPerCSSPixel(1),
94 mBoundingCompositionSize(0, 0),
96 mLayoutViewport(0, 0, 0, 0),
97 mVisualDestination(0, 0),
98 mVisualScrollUpdateType(eNone
),
99 mIsRootContent(false),
100 mIsScrollInfoLayer(false),
101 mHasNonZeroDisplayPortMargins(false),
102 mMinimalDisplayPort(false) {}
104 // Default copy ctor and operator= are fine
106 bool operator==(const FrameMetrics
& aOther
) const {
107 // Put mScrollId at the top since it's the most likely one to fail.
108 return mScrollId
== aOther
.mScrollId
&&
109 mPresShellResolution
== aOther
.mPresShellResolution
&&
110 mCompositionBounds
.IsEqualEdges(aOther
.mCompositionBounds
) &&
111 mCompositionBoundsWidthIgnoringScrollbars
==
112 aOther
.mCompositionBoundsWidthIgnoringScrollbars
&&
113 mDisplayPort
.IsEqualEdges(aOther
.mDisplayPort
) &&
114 mScrollableRect
.IsEqualEdges(aOther
.mScrollableRect
) &&
115 mCumulativeResolution
== aOther
.mCumulativeResolution
&&
116 mDevPixelsPerCSSPixel
== aOther
.mDevPixelsPerCSSPixel
&&
117 mScrollOffset
== aOther
.mScrollOffset
&&
118 // don't compare mZoom
119 mScrollGeneration
== aOther
.mScrollGeneration
&&
120 mBoundingCompositionSize
== aOther
.mBoundingCompositionSize
&&
121 mPresShellId
== aOther
.mPresShellId
&&
122 mLayoutViewport
.IsEqualEdges(aOther
.mLayoutViewport
) &&
123 mTransformToAncestorScale
== aOther
.mTransformToAncestorScale
&&
124 mPaintRequestTime
== aOther
.mPaintRequestTime
&&
125 mVisualDestination
== aOther
.mVisualDestination
&&
126 mVisualScrollUpdateType
== aOther
.mVisualScrollUpdateType
&&
127 mIsRootContent
== aOther
.mIsRootContent
&&
128 mIsScrollInfoLayer
== aOther
.mIsScrollInfoLayer
&&
129 mHasNonZeroDisplayPortMargins
==
130 aOther
.mHasNonZeroDisplayPortMargins
&&
131 mMinimalDisplayPort
== aOther
.mMinimalDisplayPort
&&
132 mFixedLayerMargins
== aOther
.mFixedLayerMargins
&&
133 mCompositionSizeWithoutDynamicToolbar
==
134 aOther
.mCompositionSizeWithoutDynamicToolbar
;
137 bool operator!=(const FrameMetrics
& aOther
) const {
138 return !operator==(aOther
);
141 bool IsScrollable() const {
142 return mScrollId
!= ScrollableLayerGuid::NULL_SCROLL_ID
;
145 CSSToScreenScale2D
DisplayportPixelsPerCSSPixel() const {
146 // Note: mZoom includes the async zoom. We want to include the async zoom
147 // even though the size of the pixels of our *current* displayport does not
148 // yet reflect it, because this function is used in the context of a repaint
149 // request where we'll be asking for a *new* displayport which does reflect
150 // the async zoom. Note 2: we include the transform to ancestor scale
151 // because this function (as the name implies) is used only in various
152 // displayport calculation related places, and those calculations want the
153 // transform to ancestor scale to be included becaese they want to reason
154 // about pixels which are the same size as screen pixels (so displayport
155 // sizes are e.g. limited to a multiple of the screen size). Whereas mZoom
156 // and mCumulativeResolution do not include it because of expectations of
157 // the code where they are used.
158 return mZoom
* mTransformToAncestorScale
;
161 CSSToLayerScale
LayersPixelsPerCSSPixel() const {
162 return mDevPixelsPerCSSPixel
* mCumulativeResolution
;
165 // Get the amount by which this frame has been zoomed since the last repaint.
166 LayerToParentLayerScale
GetAsyncZoom() const {
167 return mZoom
/ LayersPixelsPerCSSPixel();
170 // Ensure the scrollableRect is at least as big as the compositionBounds
171 // because the scrollableRect can be smaller if the content is not large
172 // and the scrollableRect hasn't been updated yet.
173 // We move the scrollableRect up because we don't know if we can move it
174 // down. i.e. we know that scrollableRect can go back as far as zero.
175 // but we don't know how much further ahead it can go.
176 CSSRect
GetExpandedScrollableRect() const {
177 CSSRect scrollableRect
= mScrollableRect
;
178 CSSSize compSize
= CalculateCompositedSizeInCssPixels();
179 if (scrollableRect
.Width() < compSize
.width
) {
180 scrollableRect
.SetRectX(
181 std::max(0.f
, scrollableRect
.X() -
182 (compSize
.width
- scrollableRect
.Width())),
186 if (scrollableRect
.Height() < compSize
.height
) {
187 scrollableRect
.SetRectY(
188 std::max(0.f
, scrollableRect
.Y() -
189 (compSize
.height
- scrollableRect
.Height())),
193 return scrollableRect
;
196 CSSSize
CalculateCompositedSizeInCssPixels() const {
197 return CalculateCompositedSizeInCssPixels(mCompositionBounds
, mZoom
);
201 * Calculate the composition bounds of this frame in the CSS pixels of
202 * the content surrounding the scroll frame (OuterCSS pixels).
203 * Note that it does not make sense to ask for the composition bounds in the
204 * CSS pixels of the scrolled content (that is, regular CSS pixels),
205 * because the origin of the composition bounds is not meaningful in that
206 * coordinate space. (The size is, use CalculateCompositedSizeInCssPixels()
209 OuterCSSRect
CalculateCompositionBoundsInOuterCssPixels() const {
210 if (GetZoom() == CSSToParentLayerScale(0)) {
211 return OuterCSSRect(); // avoid division by zero
213 // The CSS pixels of the scrolled content and the CSS pixels of the
214 // surrounding content only differ if the scrolled content is rendered
215 // at a higher resolution, and the difference is the resolution.
216 return mCompositionBounds
/ GetZoom() * GetCSSToOuterCSSScale();
219 CSSSize
CalculateBoundedCompositedSizeInCssPixels() const {
220 CSSSize size
= CalculateCompositedSizeInCssPixels();
221 size
.width
= std::min(size
.width
, mBoundingCompositionSize
.width
);
222 size
.height
= std::min(size
.height
, mBoundingCompositionSize
.height
);
226 CSSRect
CalculateScrollRange() const {
227 return CalculateScrollRange(mScrollableRect
, mCompositionBounds
, mZoom
);
230 void ScrollBy(const CSSPoint
& aPoint
) {
231 SetVisualScrollOffset(GetVisualScrollOffset() + aPoint
);
234 void ZoomBy(float aScale
) { mZoom
.scale
*= aScale
; }
237 * Compares an APZ frame metrics with an incoming content frame metrics
238 * to see if APZ has a scroll offset that has not been incorporated into
239 * the content frame metrics.
241 bool HasPendingScroll(const FrameMetrics
& aContentFrameMetrics
) const {
242 return GetVisualScrollOffset() !=
243 aContentFrameMetrics
.GetVisualScrollOffset();
247 * Returns true if the layout scroll offset or visual scroll offset changed.
249 bool ApplyScrollUpdateFrom(const ScrollPositionUpdate
& aUpdate
);
252 * Applies the relative scroll offset update contained in aOther to the
253 * scroll offset contained in this. The scroll delta is clamped to the
256 * @returns The clamped scroll offset delta that was applied
258 CSSPoint
ApplyRelativeScrollUpdateFrom(const ScrollPositionUpdate
& aUpdate
);
260 CSSPoint
ApplyPureRelativeScrollUpdateFrom(
261 const ScrollPositionUpdate
& aUpdate
);
263 void UpdatePendingScrollInfo(const ScrollPositionUpdate
& aInfo
);
266 void SetPresShellResolution(float aPresShellResolution
) {
267 mPresShellResolution
= aPresShellResolution
;
270 float GetPresShellResolution() const { return mPresShellResolution
; }
272 void SetCompositionBounds(const ParentLayerRect
& aCompositionBounds
) {
273 mCompositionBounds
= aCompositionBounds
;
276 const ParentLayerRect
& GetCompositionBounds() const {
277 return mCompositionBounds
;
280 void SetCompositionBoundsWidthIgnoringScrollbars(
281 const ParentLayerCoord aCompositionBoundsWidthIgnoringScrollbars
) {
282 mCompositionBoundsWidthIgnoringScrollbars
=
283 aCompositionBoundsWidthIgnoringScrollbars
;
286 const ParentLayerCoord
GetCompositionBoundsWidthIgnoringScrollbars() const {
287 return mCompositionBoundsWidthIgnoringScrollbars
;
290 void SetDisplayPort(const CSSRect
& aDisplayPort
) {
291 mDisplayPort
= aDisplayPort
;
294 const CSSRect
& GetDisplayPort() const { return mDisplayPort
; }
296 void SetCumulativeResolution(
297 const LayoutDeviceToLayerScale
& aCumulativeResolution
) {
298 mCumulativeResolution
= aCumulativeResolution
;
301 const LayoutDeviceToLayerScale
& GetCumulativeResolution() const {
302 return mCumulativeResolution
;
305 void SetDevPixelsPerCSSPixel(
306 const CSSToLayoutDeviceScale
& aDevPixelsPerCSSPixel
) {
307 mDevPixelsPerCSSPixel
= aDevPixelsPerCSSPixel
;
310 const CSSToLayoutDeviceScale
& GetDevPixelsPerCSSPixel() const {
311 return mDevPixelsPerCSSPixel
;
314 CSSToOuterCSSScale
GetCSSToOuterCSSScale() const {
315 // The scale difference between CSS and OuterCSS pixels is the
316 // part of the zoom that's not subject to all enclosing content,
317 // i.e. the pres shell resolution.
318 return CSSToOuterCSSScale(mPresShellResolution
);
321 void SetIsRootContent(bool aIsRootContent
) {
322 mIsRootContent
= aIsRootContent
;
325 bool IsRootContent() const { return mIsRootContent
; }
327 // Set scroll offset, first clamping to the scroll range.
328 // Return true if it changed.
329 bool ClampAndSetVisualScrollOffset(const CSSPoint
& aScrollOffset
) {
330 CSSPoint offsetBefore
= GetVisualScrollOffset();
331 SetVisualScrollOffset(CalculateScrollRange().ClampPoint(aScrollOffset
));
332 return (offsetBefore
!= GetVisualScrollOffset());
335 CSSPoint
GetLayoutScrollOffset() const { return mLayoutViewport
.TopLeft(); }
336 // Returns true if it changed.
337 bool SetLayoutScrollOffset(const CSSPoint
& aLayoutScrollOffset
) {
338 CSSPoint offsetBefore
= GetLayoutScrollOffset();
339 mLayoutViewport
.MoveTo(aLayoutScrollOffset
);
340 return (offsetBefore
!= GetLayoutScrollOffset());
343 const CSSPoint
& GetVisualScrollOffset() const { return mScrollOffset
; }
344 void SetVisualScrollOffset(const CSSPoint
& aVisualScrollOffset
) {
345 mScrollOffset
= aVisualScrollOffset
;
348 void SetZoom(const CSSToParentLayerScale
& aZoom
) { mZoom
= aZoom
; }
350 const CSSToParentLayerScale
& GetZoom() const { return mZoom
; }
352 void SetScrollGeneration(
353 const MainThreadScrollGeneration
& aScrollGeneration
) {
354 mScrollGeneration
= aScrollGeneration
;
357 MainThreadScrollGeneration
GetScrollGeneration() const {
358 return mScrollGeneration
;
361 ViewID
GetScrollId() const { return mScrollId
; }
363 void SetScrollId(ViewID scrollId
) { mScrollId
= scrollId
; }
365 void SetBoundingCompositionSize(const CSSSize
& aBoundingCompositionSize
) {
366 mBoundingCompositionSize
= aBoundingCompositionSize
;
369 const CSSSize
& GetBoundingCompositionSize() const {
370 return mBoundingCompositionSize
;
373 uint32_t GetPresShellId() const { return mPresShellId
; }
375 void SetPresShellId(uint32_t aPresShellId
) { mPresShellId
= aPresShellId
; }
377 void SetLayoutViewport(const CSSRect
& aLayoutViewport
) {
378 mLayoutViewport
= aLayoutViewport
;
381 const CSSRect
& GetLayoutViewport() const { return mLayoutViewport
; }
383 CSSRect
GetVisualViewport() const {
384 return CSSRect(GetVisualScrollOffset(),
385 CalculateCompositedSizeInCssPixels());
388 void SetTransformToAncestorScale(
389 const ParentLayerToScreenScale2D
& aTransformToAncestorScale
) {
390 mTransformToAncestorScale
= aTransformToAncestorScale
;
393 const ParentLayerToScreenScale2D
& GetTransformToAncestorScale() const {
394 return mTransformToAncestorScale
;
397 const CSSRect
& GetScrollableRect() const { return mScrollableRect
; }
399 void SetScrollableRect(const CSSRect
& aScrollableRect
) {
400 mScrollableRect
= aScrollableRect
;
403 // If the frame is in vertical-RTL writing mode(E.g. "writing-mode:
404 // vertical-rl" in CSS), or if it's in horizontal-RTL writing-mode(E.g.
405 // "writing-mode: horizontal-tb; direction: rtl;" in CSS), then this function
406 // returns true. From the representation perspective, frames whose horizontal
407 // contents start at rightside also cause their horizontal scrollbars, if any,
408 // initially start at rightside. So we can also learn about the initial side
409 // of the horizontal scrollbar for the frame by calling this function.
410 bool IsHorizontalContentRightToLeft() const { return mScrollableRect
.x
< 0; }
412 void SetPaintRequestTime(const TimeStamp
& aTime
) {
413 mPaintRequestTime
= aTime
;
415 const TimeStamp
& GetPaintRequestTime() const { return mPaintRequestTime
; }
417 void SetIsScrollInfoLayer(bool aIsScrollInfoLayer
) {
418 mIsScrollInfoLayer
= aIsScrollInfoLayer
;
420 bool IsScrollInfoLayer() const { return mIsScrollInfoLayer
; }
422 void SetHasNonZeroDisplayPortMargins(bool aHasNonZeroDisplayPortMargins
) {
423 mHasNonZeroDisplayPortMargins
= aHasNonZeroDisplayPortMargins
;
425 bool HasNonZeroDisplayPortMargins() const {
426 return mHasNonZeroDisplayPortMargins
;
429 void SetMinimalDisplayPort(bool aMinimalDisplayPort
) {
430 mMinimalDisplayPort
= aMinimalDisplayPort
;
432 bool IsMinimalDisplayPort() const { return mMinimalDisplayPort
; }
434 void SetVisualDestination(const CSSPoint
& aVisualDestination
) {
435 mVisualDestination
= aVisualDestination
;
437 const CSSPoint
& GetVisualDestination() const { return mVisualDestination
; }
439 void SetVisualScrollUpdateType(ScrollOffsetUpdateType aUpdateType
) {
440 mVisualScrollUpdateType
= aUpdateType
;
442 ScrollOffsetUpdateType
GetVisualScrollUpdateType() const {
443 return mVisualScrollUpdateType
;
446 // Determine if the visual viewport is outside of the layout viewport and
447 // adjust the x,y-offset in mLayoutViewport accordingly. This is necessary to
448 // allow APZ to async-scroll the layout viewport.
450 // This is a no-op if mIsRootContent is false.
451 void RecalculateLayoutViewportOffset();
453 void SetFixedLayerMargins(const ScreenMargin
& aFixedLayerMargins
) {
454 mFixedLayerMargins
= aFixedLayerMargins
;
456 const ScreenMargin
& GetFixedLayerMargins() const {
457 return mFixedLayerMargins
;
460 void SetCompositionSizeWithoutDynamicToolbar(const ParentLayerSize
& aSize
) {
461 MOZ_ASSERT(mIsRootContent
);
462 mCompositionSizeWithoutDynamicToolbar
= aSize
;
464 const ParentLayerSize
& GetCompositionSizeWithoutDynamicToolbar() const {
465 MOZ_ASSERT(mIsRootContent
);
466 return mCompositionSizeWithoutDynamicToolbar
;
469 // Helper function for RecalculateViewportOffset(). Exposed so that
470 // APZC can perform the operation on other copies of the layout
471 // and visual viewport rects (e.g. the "effective" ones used to implement
473 // Modifies |aLayoutViewport| to continue enclosing |aVisualViewport|
475 // The layout viewport needs to remain clamped to the scrollable rect,
476 // and we pass in the scrollable rect so this function can maintain that
478 static void KeepLayoutViewportEnclosingVisualViewport(
479 const CSSRect
& aVisualViewport
, const CSSRect
& aScrollableRect
,
480 CSSRect
& aLayoutViewport
);
482 // Helper functions exposed so we can perform operations on copies outside of
483 // frame metrics object.
484 static CSSRect
CalculateScrollRange(const CSSRect
& aScrollableRect
,
485 const ParentLayerRect
& aCompositionBounds
,
486 const CSSToParentLayerScale
& aZoom
);
487 static CSSSize
CalculateCompositedSizeInCssPixels(
488 const ParentLayerRect
& aCompositionBounds
,
489 const CSSToParentLayerScale
& aZoom
);
492 // A ID assigned to each scrollable frame, unique within each LayersId..
495 // The pres-shell resolution that has been induced on the document containing
496 // this scroll frame as a result of zooming this scroll frame (whether via
497 // user action, or choosing an initial zoom level on page load). This can
498 // only be different from 1.0 for frames that are zoomable, which currently
499 // is just the root content document's root scroll frame
500 // (mIsRootContent = true).
501 // This is a plain float rather than a ScaleFactor because in and of itself
502 // it does not convert between any coordinate spaces for which we have names.
503 float mPresShellResolution
;
505 // This is the area within the widget that we're compositing to. It is in the
506 // layer coordinates of the scrollable content's parent layer.
508 // The size of the composition bounds corresponds to the size of the scroll
509 // frame's scroll port (but in a coordinate system where the size does not
510 // change during zooming).
512 // The origin of the composition bounds is relative to the scroll node origin.
513 // (The "scroll node origin" is the point such that applying the APZC's
514 // apzc-to-screen transform to it takes you to the window origin, which is
515 // what Screen event coordinates are relative to. In layout terms, it's
516 // the origin of the reference frame passed to ComputeScrollMetadata().)
517 // Unlike the scroll port's origin, it does not change during scrolling of
518 // the scrollable layer to which it is associated. However, it may change due
519 // to scrolling of ancestor layers.
521 // This value is provided by Gecko at layout/paint time.
522 ParentLayerRect mCompositionBounds
;
524 // For RCD-RSF this is the width of the composition bounds ignoring
525 // scrollbars. For everything else this will be the same as the width of the
526 // composition bounds. Only needed for the "resolution changed" check in
527 // NotifyLayersUpdated, once that switches to using IsResolutionUpdated we can
529 ParentLayerCoord mCompositionBoundsWidthIgnoringScrollbars
;
531 // The area of a scroll frame's contents that has been painted, relative to
532 // GetLayoutScrollOffset().
534 // Should not be larger than GetExpandedScrollableRect().
536 // To pre-render a margin of 100 CSS pixels around the scroll port,
537 // { x = -100, y = - 100,
538 // width = scrollPort.width + 200, height = scrollPort.height + 200 }
539 // where scrollPort = CalculateCompositedSizeInCssPixels().
540 CSSRect mDisplayPort
;
542 // The scrollable bounds of a frame. This is determined by reflow.
543 // Ordinarily the x and y will be 0 and the width and height will be the
544 // size of the element being scrolled. However for RTL pages or elements
545 // the x value may be negative.
547 // For scrollable frames that are overflow:hidden the x and y are usually
548 // set to the value of the current scroll offset, and the width and height
549 // will match the composition bounds width and height. In effect this reduces
550 // the scrollable range to 0.
552 // This is in the same coordinate space as |mScrollOffset|, but a different
553 // coordinate space than |mDisplayPort|. Note also that this coordinate
554 // system is understood by window.scrollTo().
555 CSSRect mScrollableRect
;
557 // The cumulative resolution of the current frame. This is the product of the
558 // pres-shell resolutions of the document containing this scroll frame and its
559 // in-process ancestors. This information is provided by Gecko at layout/paint
560 // time. Notably, for out of process iframes cumulative resolution will be 1.
561 // The reason for this is that AsyncPanZoomController::GetTransformToThis does
562 // not contain the resolution in the process of the root content document, but
563 // in oop iframes AsyncPanZoomController::GetTransformToThis does contain the
564 // resolution. This makes coordinate math work out in APZ code because in the
565 // old layers backend GetTransformToThis was a transform of rendered pixels,
566 // and the pixels were rendered with the scale applied already. The reason
567 // that AsyncPanZoomController::GetTransformToThis contains the scale in oop
568 // iframes is because we include the resolution in the transform that includes
569 // the iframe via this call
570 // https://searchfox.org/mozilla-central/rev/2eebd6e256fa0355e08421265e57ee1307836d92/layout/generic/nsSubDocumentFrame.cpp#1404
571 // So when coordinates are passed to the process of the oop iframe they have
572 // the resolution removed by unapplying that transform which includes the
574 LayoutDeviceToLayerScale mCumulativeResolution
;
576 // The conversion factor between CSS pixels and device pixels for this frame.
577 // This can vary based on a variety of things, such as reflowing-zoom.
578 CSSToLayoutDeviceScale mDevPixelsPerCSSPixel
;
580 // The position of the top-left of the scroll frame's scroll port, relative
581 // to the scrollable content's origin.
583 // This is in the same coordinate space as |mScrollableRect|, but a different
584 // coordinate space than |mDisplayPort|.
586 // It is required that the rect:
587 // { x = mScrollOffset.x, y = mScrollOffset.y,
588 // width = scrollPort.width,
589 // height = scrollPort.height }
590 // (where scrollPort = CalculateCompositedSizeInCssPixels())
591 // be within |mScrollableRect|.
592 CSSPoint mScrollOffset
;
594 // The "user zoom". Content is painted by gecko at mCumulativeResolution *
595 // mDevPixelsPerCSSPixel, but will be drawn to the screen at mZoom. In the
596 // steady state, the two will be the same, but during an async zoom action the
597 // two may diverge. This information is initialized in Gecko but updated in
599 CSSToParentLayerScale mZoom
;
601 // The scroll generation counter used to acknowledge the scroll offset update.
602 MainThreadScrollGeneration mScrollGeneration
;
604 // A bounding size for our composition bounds (no larger than the
605 // cross-process RCD-RSF's composition size), in local CSS pixels.
606 CSSSize mBoundingCompositionSize
;
608 uint32_t mPresShellId
;
610 // For a root scroll frame (RSF), the document's layout viewport
611 // (sometimes called "CSS viewport" in older code).
613 // Its size is the dimensions we're using to constrain the <html> element
614 // of the document (i.e. the initial containing block (ICB) size).
616 // Its origin is the RSF's layout scroll position, i.e. the scroll position
617 // exposed to web content via window.scrollX/Y.
619 // Note that only the root content document's RSF has a layout viewport
620 // that's distinct from the visual viewport. For an iframe RSF, the two
623 // For a scroll frame that is not an RSF, this metric is meaningless and
625 CSSRect mLayoutViewport
;
627 // The scale induced by css transforms and presshell resolution in this
628 // process and any ancestor processes that encloses this scroll frame that is
629 // _not_ included in mCumulativeResolution. This means that in the process of
630 // the root content document this only includes css transform scale (which
631 // happens in that process, but we assume there can be no css transform scale
632 // above the root content document). In other processes it includes css
633 // transform scale and any resolution scale in the current process and all
634 // ancestor processes.
635 ParentLayerToScreenScale2D mTransformToAncestorScale
;
637 // The time at which the APZC last requested a repaint for this scroll frame.
638 TimeStamp mPaintRequestTime
;
640 // These fields are used when the main thread wants to set a visual viewport
641 // offset that's distinct from the layout viewport offset.
642 // In this case, mVisualScrollUpdateType is set to eMainThread, and
643 // mVisualDestination is set to desired visual destination (relative
644 // to the document, like mScrollOffset).
645 CSSPoint mVisualDestination
;
646 ScrollOffsetUpdateType mVisualScrollUpdateType
;
648 // 'fixed layer margins' on the main-thread. This is only used for the
649 // root-content scroll frame.
650 ScreenMargin mFixedLayerMargins
;
652 // Similar to mCompositionBounds.Size() but not including the dynamic toolbar
654 // If we are not using a dynamic toolbar, this has the same value as
655 // mCompositionBounds.Size().
656 ParentLayerSize mCompositionSizeWithoutDynamicToolbar
;
658 // Whether or not this is the root scroll frame for the root content document.
659 bool mIsRootContent
: 1;
661 // True if this scroll frame is a scroll info layer. A scroll info layer is
662 // not layerized and its content cannot be truly async-scrolled, but its
663 // metrics are still sent to and updated by the compositor, with the updates
664 // being reflected on the next paint rather than the next composite.
665 bool mIsScrollInfoLayer
: 1;
667 // Whether there are non-zero display port margins set on this element.
668 bool mHasNonZeroDisplayPortMargins
: 1;
670 // Whether this scroll frame is using a minimal display port, which means that
671 // any set display port margins are ignored when calculating the display port
672 // and instead zero margins are used and further no tile or alignment
673 // boundaries are used that could potentially expand the size.
674 bool mMinimalDisplayPort
: 1;
678 // When adding a new field:
680 // - First, consider whether the field can be added to ScrollMetadata
681 // instead. If so, prefer that.
683 // - Otherwise, the following places should be updated to include them
685 // FrameMetrics::operator ==
686 // AsyncPanZoomController::NotifyLayersUpdated
687 // The ParamTraits specialization in LayersMessageUtils.h
689 // Please add new fields above this comment.
693 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
694 OverscrollBehavior
, uint8_t, (
701 std::ostream
& operator<<(std::ostream
& aStream
,
702 const OverscrollBehavior
& aBehavior
);
704 struct OverscrollBehaviorInfo final
{
705 OverscrollBehaviorInfo();
707 // Construct from StyleOverscrollBehavior values.
708 static OverscrollBehaviorInfo
FromStyleConstants(
709 StyleOverscrollBehavior aBehaviorX
, StyleOverscrollBehavior aBehaviorY
);
711 bool operator==(const OverscrollBehaviorInfo
& aOther
) const;
712 friend std::ostream
& operator<<(std::ostream
& aStream
,
713 const OverscrollBehaviorInfo
& aInfo
);
715 auto MutTiedFields() { return std::tie(mBehaviorX
, mBehaviorY
); }
717 OverscrollBehavior mBehaviorX
;
718 OverscrollBehavior mBehaviorY
;
721 struct OverflowInfo final
{
722 StyleOverflow mOverflowX
= StyleOverflow::Visible
;
723 StyleOverflow mOverflowY
= StyleOverflow::Visible
;
725 bool operator==(const OverflowInfo
& aOther
) const;
727 auto MutTiedFields() { return std::tie(mOverflowX
, mOverflowY
); }
731 * Metadata about a scroll frame that's sent to the compositor during a layers
732 * or WebRender transaction, and also stored by APZ between transactions.
733 * This includes the scroll frame's FrameMetrics, as well as other metadata.
734 * We don't put the other metadata into FrameMetrics to avoid FrameMetrics
735 * becoming too bloated (as a FrameMetrics is e.g. stored in memory shared
736 * with the content process).
738 struct ScrollMetadata
{
739 friend struct IPC::ParamTraits
<mozilla::layers::ScrollMetadata
>;
740 friend std::ostream
& operator<<(std::ostream
& aStream
,
741 const ScrollMetadata
& aMetadata
);
743 typedef ScrollableLayerGuid::ViewID ViewID
;
746 static StaticAutoPtr
<const ScrollMetadata
>
747 sNullMetadata
; // We sometimes need an empty metadata
750 : mScrollParentId(ScrollableLayerGuid::NULL_SCROLL_ID
),
751 mLineScrollAmount(0, 0),
752 mPageScrollAmount(0, 0),
754 dom::InteractiveWidgetUtils::DefaultInteractiveWidgetMode()),
755 mHasScrollgrab(false),
756 mIsLayersIdRoot(false),
757 mIsAutoDirRootContentRTL(false),
758 mForceDisableApz(false),
759 mResolutionUpdated(false),
760 mIsRDMTouchSimulationActive(false),
761 mDidContentGetPainted(true),
762 mForceMousewheelAutodir(false),
763 mForceMousewheelAutodirHonourRoot(false),
764 mIsPaginatedPresentation(false),
765 mIsSoftwareKeyboardVisible(false) {}
767 bool operator==(const ScrollMetadata
& aOther
) const {
768 return mMetrics
== aOther
.mMetrics
&& mSnapInfo
== aOther
.mSnapInfo
&&
769 mScrollParentId
== aOther
.mScrollParentId
&&
770 // don't compare mContentDescription
771 mLineScrollAmount
== aOther
.mLineScrollAmount
&&
772 mPageScrollAmount
== aOther
.mPageScrollAmount
&&
773 mInteractiveWidget
== aOther
.mInteractiveWidget
&&
774 mHasScrollgrab
== aOther
.mHasScrollgrab
&&
775 mIsLayersIdRoot
== aOther
.mIsLayersIdRoot
&&
776 mIsAutoDirRootContentRTL
== aOther
.mIsAutoDirRootContentRTL
&&
777 mForceDisableApz
== aOther
.mForceDisableApz
&&
778 mResolutionUpdated
== aOther
.mResolutionUpdated
&&
779 mIsRDMTouchSimulationActive
== aOther
.mIsRDMTouchSimulationActive
&&
780 mDidContentGetPainted
== aOther
.mDidContentGetPainted
&&
781 mForceMousewheelAutodir
== aOther
.mForceMousewheelAutodir
&&
782 mForceMousewheelAutodirHonourRoot
==
783 aOther
.mForceMousewheelAutodirHonourRoot
&&
784 mIsPaginatedPresentation
== aOther
.mIsPaginatedPresentation
&&
785 mIsSoftwareKeyboardVisible
== aOther
.mIsSoftwareKeyboardVisible
&&
786 mDisregardedDirection
== aOther
.mDisregardedDirection
&&
787 mOverscrollBehavior
== aOther
.mOverscrollBehavior
&&
788 mOverflow
== aOther
.mOverflow
&&
789 mScrollUpdates
== aOther
.mScrollUpdates
;
792 bool operator!=(const ScrollMetadata
& aOther
) const {
793 return !operator==(aOther
);
796 bool IsDefault() const {
799 def
.mMetrics
.SetPresShellId(mMetrics
.GetPresShellId());
800 return (def
== *this);
803 FrameMetrics
& GetMetrics() { return mMetrics
; }
804 const FrameMetrics
& GetMetrics() const { return mMetrics
; }
806 void SetSnapInfo(ScrollSnapInfo
&& aSnapInfo
) {
807 mSnapInfo
= std::move(aSnapInfo
);
809 const ScrollSnapInfo
& GetSnapInfo() const { return mSnapInfo
; }
811 ViewID
GetScrollParentId() const { return mScrollParentId
; }
813 void SetScrollParentId(ViewID aParentId
) { mScrollParentId
= aParentId
; }
814 const nsCString
& GetContentDescription() const { return mContentDescription
; }
815 void SetContentDescription(const nsCString
& aContentDescription
) {
816 mContentDescription
= aContentDescription
;
818 const LayoutDeviceIntSize
& GetLineScrollAmount() const {
819 return mLineScrollAmount
;
821 void SetLineScrollAmount(const LayoutDeviceIntSize
& size
) {
822 mLineScrollAmount
= size
;
824 const LayoutDeviceIntSize
& GetPageScrollAmount() const {
825 return mPageScrollAmount
;
827 void SetPageScrollAmount(const LayoutDeviceIntSize
& size
) {
828 mPageScrollAmount
= size
;
830 void SetHasScrollgrab(bool aHasScrollgrab
) {
831 mHasScrollgrab
= aHasScrollgrab
;
833 bool GetHasScrollgrab() const { return mHasScrollgrab
; }
834 void SetIsLayersIdRoot(bool aValue
) { mIsLayersIdRoot
= aValue
; }
835 bool IsLayersIdRoot() const { return mIsLayersIdRoot
; }
836 void SetIsAutoDirRootContentRTL(bool aValue
) {
837 mIsAutoDirRootContentRTL
= aValue
;
839 bool IsAutoDirRootContentRTL() const { return mIsAutoDirRootContentRTL
; }
840 void SetForceDisableApz(bool aForceDisable
) {
841 mForceDisableApz
= aForceDisable
;
843 bool IsApzForceDisabled() const { return mForceDisableApz
; }
844 void SetResolutionUpdated(bool aUpdated
) { mResolutionUpdated
= aUpdated
; }
845 bool IsResolutionUpdated() const { return mResolutionUpdated
; }
847 void SetIsRDMTouchSimulationActive(bool aValue
) {
848 mIsRDMTouchSimulationActive
= aValue
;
850 bool GetIsRDMTouchSimulationActive() const {
851 return mIsRDMTouchSimulationActive
;
854 void SetForceMousewheelAutodir(bool aValue
) {
855 mForceMousewheelAutodir
= aValue
;
857 bool ForceMousewheelAutodir() const { return mForceMousewheelAutodir
; }
859 void SetForceMousewheelAutodirHonourRoot(bool aValue
) {
860 mForceMousewheelAutodirHonourRoot
= aValue
;
862 bool ForceMousewheelAutodirHonourRoot() const {
863 return mForceMousewheelAutodirHonourRoot
;
866 void SetIsPaginatedPresentation(bool aValue
) {
867 mIsPaginatedPresentation
= aValue
;
869 bool IsPaginatedPresentation() const { return mIsPaginatedPresentation
; }
871 void SetIsSoftwareKeyboardVisible(bool aValue
) {
872 mIsSoftwareKeyboardVisible
= aValue
;
874 bool IsSoftwareKeyboardVisible() const { return mIsSoftwareKeyboardVisible
; }
876 void SetInteractiveWidget(dom::InteractiveWidget aInteractiveWidget
) {
877 mInteractiveWidget
= aInteractiveWidget
;
879 dom::InteractiveWidget
GetInteractiveWidget() const {
880 return mInteractiveWidget
;
883 bool DidContentGetPainted() const { return mDidContentGetPainted
; }
886 // For use in IPC only
887 void SetDidContentGetPainted(bool aValue
) { mDidContentGetPainted
= aValue
; }
890 // For more details about the concept of a disregarded direction, refer to the
891 // code which defines mDisregardedDirection.
892 Maybe
<ScrollDirection
> GetDisregardedDirection() const {
893 return mDisregardedDirection
;
895 void SetDisregardedDirection(const Maybe
<ScrollDirection
>& aValue
) {
896 mDisregardedDirection
= aValue
;
899 void SetOverscrollBehavior(
900 const OverscrollBehaviorInfo
& aOverscrollBehavior
) {
901 mOverscrollBehavior
= aOverscrollBehavior
;
903 const OverscrollBehaviorInfo
& GetOverscrollBehavior() const {
904 return mOverscrollBehavior
;
907 void SetOverflow(const OverflowInfo
& aOverflow
) { mOverflow
= aOverflow
; }
908 const OverflowInfo
& GetOverflow() const { return mOverflow
; }
910 void SetScrollUpdates(const nsTArray
<ScrollPositionUpdate
>& aUpdates
) {
911 mScrollUpdates
= aUpdates
;
914 const nsTArray
<ScrollPositionUpdate
>& GetScrollUpdates() const {
915 return mScrollUpdates
;
918 void UpdatePendingScrollInfo(nsTArray
<ScrollPositionUpdate
>&& aUpdates
) {
919 MOZ_ASSERT(!aUpdates
.IsEmpty());
920 mMetrics
.UpdatePendingScrollInfo(aUpdates
.LastElement());
922 mDidContentGetPainted
= false;
923 mScrollUpdates
.Clear();
924 mScrollUpdates
.AppendElements(std::move(aUpdates
));
927 void PrependUpdates(const nsTArray
<ScrollPositionUpdate
>& aUpdates
) {
928 MOZ_ASSERT(!aUpdates
.IsEmpty());
930 mScrollUpdates
.InsertElementsAt(0, aUpdates
);
934 FrameMetrics mMetrics
;
936 // Information used to determine where to snap to for a given scroll.
937 ScrollSnapInfo mSnapInfo
;
939 // The ViewID of the scrollable frame to which overscroll should be handed
941 ViewID mScrollParentId
;
943 // A description of the content element corresponding to this frame.
944 // This is empty unless this is a scrollable layer and the
945 // apz.printtree pref is turned on.
946 nsCString mContentDescription
;
948 // The value of GetLineScrollAmount(), for scroll frames.
949 LayoutDeviceIntSize mLineScrollAmount
;
951 // The value of GetPageScrollAmount(), for scroll frames.
952 LayoutDeviceIntSize mPageScrollAmount
;
954 // The interactive-widget of the root-content document.
955 // This is only applicable to the root-content scroll frame, it's stored in
956 // APZTreeManager as APZTreeManager::mInteractiveWidget so that it should not
957 // be checked on AsyncPanZoomController::mScrollMetadata.
958 dom::InteractiveWidget mInteractiveWidget
;
960 // Whether or not this frame is for an element marked 'scrollgrab'.
961 bool mHasScrollgrab
: 1;
963 // Whether these framemetrics are for the root scroll frame (root element if
964 // we don't have a root scroll frame) for its layers id.
965 bool mIsLayersIdRoot
: 1;
967 // The AutoDirRootContent is the <body> element in an HTML document, or the
968 // root scrollframe if there is no body. This member variable indicates
969 // whether this element's content in the horizontal direction starts from
970 // right to left (e.g. it's true either if "writing-mode: vertical-rl", or
971 // "writing-mode: horizontal-tb; direction: rtl" in CSS).
972 // When we do auto-dir scrolling (@see mozilla::WheelDeltaAdjustmentStrategy
973 // or refer to bug 1358017 for details), setting a pref can make the code use
974 // the writing mode of this root element instead of the target scrollframe,
975 // and so we need to know if the writing mode is RTL or not.
976 bool mIsAutoDirRootContentRTL
: 1;
978 // Whether or not the compositor should actually do APZ-scrolling on this
980 bool mForceDisableApz
: 1;
982 // Whether the pres shell resolution stored in mMetrics reflects a change
983 // originated by the main thread.
984 bool mResolutionUpdated
: 1;
986 // Whether or not RDM and touch simulation are active for this document.
987 // It's important to note that if RDM is active then this field will be
988 // true for the content document but NOT the chrome document containing
989 // the browser UI and RDM controls.
990 bool mIsRDMTouchSimulationActive
: 1;
992 // Whether this metadata is part of a transaction that also repainted the
993 // content (i.e. updated the displaylist or textures). This gets set to false
994 // for "paint-skip" transactions, where the main thread doesn't repaint but
995 // instead requests APZ to update the compositor scroll offset instead. APZ
996 // needs to be able to distinguish these paint-skip transactions so that it
997 // can use the correct transforms.
998 bool mDidContentGetPainted
: 1;
1000 // Whether privileged code has requested that autodir behaviour be
1001 // enabled for the scroll frame.
1002 bool mForceMousewheelAutodir
: 1;
1003 bool mForceMousewheelAutodirHonourRoot
: 1;
1005 // Whether this content is being displayed in a paginated fashion
1006 // such as printing or print preview. In such cases, content that
1007 // would normally only generate one display item may generated one
1008 // display item per page, and the different instances may be subject
1009 // to different transforms, which constrains the assumptions APZ can make.
1010 bool mIsPaginatedPresentation
: 1;
1012 // Whether the software keyboard is currently visible.
1013 // This is only applicable to the root-content scroll frame, it's stored in
1014 // APZTreeManager as APZTreeManager::mIsSoftwareKeyboardVisible so that it
1015 // should not be checked on AsyncPanZoomController::mScrollMetadata.
1016 bool mIsSoftwareKeyboardVisible
: 1;
1018 // The disregarded direction means the direction which is disregarded anyway,
1019 // even if the scroll frame overflows in that direction and the direction is
1020 // specified as scrollable. This could happen in some scenarios, for instance,
1021 // a single-line text control frame should disregard wheel scroll in
1022 // its block-flow direction even if it overflows in that direction.
1023 Maybe
<ScrollDirection
> mDisregardedDirection
;
1025 // The overscroll behavior for this scroll frame.
1026 OverscrollBehaviorInfo mOverscrollBehavior
;
1028 // The CSS overflow styles for this scroll frame.
1029 // For a root scroll frame, this stores the viewport styles
1030 // as defined in https://drafts.csswg.org/css-overflow/#overflow-propagation
1031 // (i.e. they will always be 'auto', 'hidden', or 'scrol').
1032 OverflowInfo mOverflow
;
1034 // The ordered list of scroll position updates for this scroll frame since
1035 // the last transaction.
1036 CopyableTArray
<ScrollPositionUpdate
> mScrollUpdates
;
1040 // When adding new fields to ScrollMetadata, the following places should be
1041 // updated to include them (as needed):
1042 // 1. ScrollMetadata::operator ==
1043 // 2. AsyncPanZoomController::NotifyLayersUpdated
1044 // 3. The ParamTraits specialization in LayersMessageUtils.h
1046 // Please add new fields above this comment.
1049 typedef nsTHashMap
<ScrollableLayerGuid::ViewIDHashKey
,
1050 nsTArray
<ScrollPositionUpdate
>>
1053 } // namespace layers
1054 } // namespace mozilla
1056 #endif /* GFX_FRAMEMETRICS_H */