Bug 1882457 - Update the release process docs for the monorepo migration. r=ahal...
[gecko.git] / gfx / layers / FrameMetrics.h
blob5d13d36703cddda0d14b1365658bbcb9055a05f6
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
11 #include <iosfwd>
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
30 #include "nsString.h"
31 #include "PLDHashTable.h" // for PLDHashNumber
33 struct nsStyleDisplay;
34 namespace mozilla {
35 enum class StyleOverscrollBehavior : uint8_t;
36 } // namespace mozilla
38 namespace IPC {
39 template <typename T>
40 struct ParamTraits;
41 } // namespace IPC
43 namespace mozilla {
44 namespace layers {
46 /**
47 * Metrics about a scroll frame that are sent to the compositor and used
48 * by APZ.
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.
63 struct FrameMetrics {
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;
70 public:
71 // clang-format off
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
80 // already.
81 ));
82 // clang-format on
84 FrameMetrics()
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),
92 mScrollOffset(0, 0),
93 mBoundingCompositionSize(0, 0),
94 mPresShellId(-1),
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())),
182 compSize.width);
185 if (scrollableRect.Height() < compSize.height) {
186 scrollableRect.SetRectY(
187 std::max(0.f, scrollableRect.Y() -
188 (compSize.height - scrollableRect.Height())),
189 compSize.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()
206 * for that.)
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);
222 return size;
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
253 * scrollable region.
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);
264 public:
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
471 // the frame delay).
472 // Modifies |aLayoutViewport| to continue enclosing |aVisualViewport|
473 // if possible.
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
476 // constraint.
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);
490 private:
491 // A ID assigned to each scrollable frame, unique within each LayersId..
492 ViewID mScrollId;
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
527 // remove this.
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
572 // resolution.
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
597 // the APZC.
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
620 // are the same.
622 // For a scroll frame that is not an RSF, this metric is meaningless and
623 // invalid.
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
652 // height.
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;
675 // WARNING!!!!
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
683 // (as needed):
684 // FrameMetrics::operator ==
685 // AsyncPanZoomController::NotifyLayersUpdated
686 // The ParamTraits specialization in LayersMessageUtils.h
688 // Please add new fields above this comment.
691 // clang-format off
692 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
693 OverscrollBehavior, uint8_t, (
694 Auto,
695 Contain,
696 None
698 // clang-format on
700 std::ostream& operator<<(std::ostream& aStream,
701 const OverscrollBehavior& aBehavior);
703 struct OverscrollBehaviorInfo {
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 OverscrollBehavior mBehaviorX;
715 OverscrollBehavior mBehaviorY;
719 * Metadata about a scroll frame that's sent to the compositor during a layers
720 * or WebRender transaction, and also stored by APZ between transactions.
721 * This includes the scroll frame's FrameMetrics, as well as other metadata.
722 * We don't put the other metadata into FrameMetrics to avoid FrameMetrics
723 * becoming too bloated (as a FrameMetrics is e.g. stored in memory shared
724 * with the content process).
726 struct ScrollMetadata {
727 friend struct IPC::ParamTraits<mozilla::layers::ScrollMetadata>;
728 friend std::ostream& operator<<(std::ostream& aStream,
729 const ScrollMetadata& aMetadata);
731 typedef ScrollableLayerGuid::ViewID ViewID;
733 public:
734 static StaticAutoPtr<const ScrollMetadata>
735 sNullMetadata; // We sometimes need an empty metadata
737 ScrollMetadata()
738 : mScrollParentId(ScrollableLayerGuid::NULL_SCROLL_ID),
739 mLineScrollAmount(0, 0),
740 mPageScrollAmount(0, 0),
741 mHasScrollgrab(false),
742 mIsLayersIdRoot(false),
743 mIsAutoDirRootContentRTL(false),
744 mForceDisableApz(false),
745 mResolutionUpdated(false),
746 mIsRDMTouchSimulationActive(false),
747 mDidContentGetPainted(true),
748 mForceMousewheelAutodir(false),
749 mForceMousewheelAutodirHonourRoot(false),
750 mIsPaginatedPresentation(false) {}
752 bool operator==(const ScrollMetadata& aOther) const {
753 return mMetrics == aOther.mMetrics && mSnapInfo == aOther.mSnapInfo &&
754 mScrollParentId == aOther.mScrollParentId &&
755 // don't compare mContentDescription
756 mLineScrollAmount == aOther.mLineScrollAmount &&
757 mPageScrollAmount == aOther.mPageScrollAmount &&
758 mHasScrollgrab == aOther.mHasScrollgrab &&
759 mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
760 mIsAutoDirRootContentRTL == aOther.mIsAutoDirRootContentRTL &&
761 mForceDisableApz == aOther.mForceDisableApz &&
762 mResolutionUpdated == aOther.mResolutionUpdated &&
763 mIsRDMTouchSimulationActive == aOther.mIsRDMTouchSimulationActive &&
764 mDidContentGetPainted == aOther.mDidContentGetPainted &&
765 mForceMousewheelAutodir == aOther.mForceMousewheelAutodir &&
766 mForceMousewheelAutodirHonourRoot ==
767 aOther.mForceMousewheelAutodirHonourRoot &&
768 mIsPaginatedPresentation == aOther.mIsPaginatedPresentation &&
769 mDisregardedDirection == aOther.mDisregardedDirection &&
770 mOverscrollBehavior == aOther.mOverscrollBehavior &&
771 mScrollUpdates == aOther.mScrollUpdates;
774 bool operator!=(const ScrollMetadata& aOther) const {
775 return !operator==(aOther);
778 bool IsDefault() const {
779 ScrollMetadata def;
781 def.mMetrics.SetPresShellId(mMetrics.GetPresShellId());
782 return (def == *this);
785 FrameMetrics& GetMetrics() { return mMetrics; }
786 const FrameMetrics& GetMetrics() const { return mMetrics; }
788 void SetSnapInfo(ScrollSnapInfo&& aSnapInfo) {
789 mSnapInfo = std::move(aSnapInfo);
791 const ScrollSnapInfo& GetSnapInfo() const { return mSnapInfo; }
793 ViewID GetScrollParentId() const { return mScrollParentId; }
795 void SetScrollParentId(ViewID aParentId) { mScrollParentId = aParentId; }
796 const nsCString& GetContentDescription() const { return mContentDescription; }
797 void SetContentDescription(const nsCString& aContentDescription) {
798 mContentDescription = aContentDescription;
800 const LayoutDeviceIntSize& GetLineScrollAmount() const {
801 return mLineScrollAmount;
803 void SetLineScrollAmount(const LayoutDeviceIntSize& size) {
804 mLineScrollAmount = size;
806 const LayoutDeviceIntSize& GetPageScrollAmount() const {
807 return mPageScrollAmount;
809 void SetPageScrollAmount(const LayoutDeviceIntSize& size) {
810 mPageScrollAmount = size;
812 void SetHasScrollgrab(bool aHasScrollgrab) {
813 mHasScrollgrab = aHasScrollgrab;
815 bool GetHasScrollgrab() const { return mHasScrollgrab; }
816 void SetIsLayersIdRoot(bool aValue) { mIsLayersIdRoot = aValue; }
817 bool IsLayersIdRoot() const { return mIsLayersIdRoot; }
818 void SetIsAutoDirRootContentRTL(bool aValue) {
819 mIsAutoDirRootContentRTL = aValue;
821 bool IsAutoDirRootContentRTL() const { return mIsAutoDirRootContentRTL; }
822 void SetForceDisableApz(bool aForceDisable) {
823 mForceDisableApz = aForceDisable;
825 bool IsApzForceDisabled() const { return mForceDisableApz; }
826 void SetResolutionUpdated(bool aUpdated) { mResolutionUpdated = aUpdated; }
827 bool IsResolutionUpdated() const { return mResolutionUpdated; }
829 void SetIsRDMTouchSimulationActive(bool aValue) {
830 mIsRDMTouchSimulationActive = aValue;
832 bool GetIsRDMTouchSimulationActive() const {
833 return mIsRDMTouchSimulationActive;
836 void SetForceMousewheelAutodir(bool aValue) {
837 mForceMousewheelAutodir = aValue;
839 bool ForceMousewheelAutodir() const { return mForceMousewheelAutodir; }
841 void SetForceMousewheelAutodirHonourRoot(bool aValue) {
842 mForceMousewheelAutodirHonourRoot = aValue;
844 bool ForceMousewheelAutodirHonourRoot() const {
845 return mForceMousewheelAutodirHonourRoot;
848 void SetIsPaginatedPresentation(bool aValue) {
849 mIsPaginatedPresentation = aValue;
851 bool IsPaginatedPresentation() const { return mIsPaginatedPresentation; }
853 bool DidContentGetPainted() const { return mDidContentGetPainted; }
855 private:
856 // For use in IPC only
857 void SetDidContentGetPainted(bool aValue) { mDidContentGetPainted = aValue; }
859 public:
860 // For more details about the concept of a disregarded direction, refer to the
861 // code which defines mDisregardedDirection.
862 Maybe<ScrollDirection> GetDisregardedDirection() const {
863 return mDisregardedDirection;
865 void SetDisregardedDirection(const Maybe<ScrollDirection>& aValue) {
866 mDisregardedDirection = aValue;
869 void SetOverscrollBehavior(
870 const OverscrollBehaviorInfo& aOverscrollBehavior) {
871 mOverscrollBehavior = aOverscrollBehavior;
873 const OverscrollBehaviorInfo& GetOverscrollBehavior() const {
874 return mOverscrollBehavior;
877 void SetScrollUpdates(const nsTArray<ScrollPositionUpdate>& aUpdates) {
878 mScrollUpdates = aUpdates;
881 const nsTArray<ScrollPositionUpdate>& GetScrollUpdates() const {
882 return mScrollUpdates;
885 void UpdatePendingScrollInfo(nsTArray<ScrollPositionUpdate>&& aUpdates) {
886 MOZ_ASSERT(!aUpdates.IsEmpty());
887 mMetrics.UpdatePendingScrollInfo(aUpdates.LastElement());
889 mDidContentGetPainted = false;
890 mScrollUpdates.Clear();
891 mScrollUpdates.AppendElements(std::move(aUpdates));
894 void PrependUpdates(const nsTArray<ScrollPositionUpdate>& aUpdates) {
895 MOZ_ASSERT(!aUpdates.IsEmpty());
897 mScrollUpdates.InsertElementsAt(0, aUpdates);
900 private:
901 FrameMetrics mMetrics;
903 // Information used to determine where to snap to for a given scroll.
904 ScrollSnapInfo mSnapInfo;
906 // The ViewID of the scrollable frame to which overscroll should be handed
907 // off.
908 ViewID mScrollParentId;
910 // A description of the content element corresponding to this frame.
911 // This is empty unless this is a scrollable layer and the
912 // apz.printtree pref is turned on.
913 nsCString mContentDescription;
915 // The value of GetLineScrollAmount(), for scroll frames.
916 LayoutDeviceIntSize mLineScrollAmount;
918 // The value of GetPageScrollAmount(), for scroll frames.
919 LayoutDeviceIntSize mPageScrollAmount;
921 // Whether or not this frame is for an element marked 'scrollgrab'.
922 bool mHasScrollgrab : 1;
924 // Whether these framemetrics are for the root scroll frame (root element if
925 // we don't have a root scroll frame) for its layers id.
926 bool mIsLayersIdRoot : 1;
928 // The AutoDirRootContent is the <body> element in an HTML document, or the
929 // root scrollframe if there is no body. This member variable indicates
930 // whether this element's content in the horizontal direction starts from
931 // right to left (e.g. it's true either if "writing-mode: vertical-rl", or
932 // "writing-mode: horizontal-tb; direction: rtl" in CSS).
933 // When we do auto-dir scrolling (@see mozilla::WheelDeltaAdjustmentStrategy
934 // or refer to bug 1358017 for details), setting a pref can make the code use
935 // the writing mode of this root element instead of the target scrollframe,
936 // and so we need to know if the writing mode is RTL or not.
937 bool mIsAutoDirRootContentRTL : 1;
939 // Whether or not the compositor should actually do APZ-scrolling on this
940 // scrollframe.
941 bool mForceDisableApz : 1;
943 // Whether the pres shell resolution stored in mMetrics reflects a change
944 // originated by the main thread.
945 bool mResolutionUpdated : 1;
947 // Whether or not RDM and touch simulation are active for this document.
948 // It's important to note that if RDM is active then this field will be
949 // true for the content document but NOT the chrome document containing
950 // the browser UI and RDM controls.
951 bool mIsRDMTouchSimulationActive : 1;
953 // Whether this metadata is part of a transaction that also repainted the
954 // content (i.e. updated the displaylist or textures). This gets set to false
955 // for "paint-skip" transactions, where the main thread doesn't repaint but
956 // instead requests APZ to update the compositor scroll offset instead. APZ
957 // needs to be able to distinguish these paint-skip transactions so that it
958 // can use the correct transforms.
959 bool mDidContentGetPainted : 1;
961 // Whether privileged code has requested that autodir behaviour be
962 // enabled for the scroll frame.
963 bool mForceMousewheelAutodir : 1;
964 bool mForceMousewheelAutodirHonourRoot : 1;
966 // Whether this content is being displayed in a paginated fashion
967 // such as printing or print preview. In such cases, content that
968 // would normally only generate one display item may generated one
969 // display item per page, and the different instances may be subject
970 // to different transforms, which constrains the assumptions APZ can make.
971 bool mIsPaginatedPresentation : 1;
973 // The disregarded direction means the direction which is disregarded anyway,
974 // even if the scroll frame overflows in that direction and the direction is
975 // specified as scrollable. This could happen in some scenarios, for instance,
976 // a single-line text control frame should disregard wheel scroll in
977 // its block-flow direction even if it overflows in that direction.
978 Maybe<ScrollDirection> mDisregardedDirection;
980 // The overscroll behavior for this scroll frame.
981 OverscrollBehaviorInfo mOverscrollBehavior;
983 // The ordered list of scroll position updates for this scroll frame since
984 // the last transaction.
985 CopyableTArray<ScrollPositionUpdate> mScrollUpdates;
987 // WARNING!!!!
989 // When adding new fields to ScrollMetadata, the following places should be
990 // updated to include them (as needed):
991 // 1. ScrollMetadata::operator ==
992 // 2. AsyncPanZoomController::NotifyLayersUpdated
993 // 3. The ParamTraits specialization in LayersMessageUtils.h
995 // Please add new fields above this comment.
998 typedef nsTHashMap<ScrollableLayerGuid::ViewIDHashKey,
999 nsTArray<ScrollPositionUpdate>>
1000 ScrollUpdatesMap;
1002 } // namespace layers
1003 } // namespace mozilla
1005 #endif /* GFX_FRAMEMETRICS_H */