Bug 1919083 - [ci] Enable os-integration variant for more suites, r=jmaher
[gecko.git] / gfx / layers / FrameMetrics.h
blob2c772daaa99567795646a07e631da7d165d77e1d
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/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
31 #include "nsString.h"
32 #include "PLDHashTable.h" // for PLDHashNumber
34 struct nsStyleDisplay;
35 namespace mozilla {
36 enum class StyleOverscrollBehavior : uint8_t;
37 } // namespace mozilla
39 namespace IPC {
40 template <typename T>
41 struct ParamTraits;
42 } // namespace IPC
44 namespace mozilla {
45 namespace layers {
47 /**
48 * Metrics about a scroll frame that are sent to the compositor and used
49 * by APZ.
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.
64 struct FrameMetrics {
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;
71 public:
72 // clang-format off
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
81 // already.
82 ));
83 // clang-format on
85 FrameMetrics()
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),
93 mScrollOffset(0, 0),
94 mBoundingCompositionSize(0, 0),
95 mPresShellId(-1),
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())),
183 compSize.width);
186 if (scrollableRect.Height() < compSize.height) {
187 scrollableRect.SetRectY(
188 std::max(0.f, scrollableRect.Y() -
189 (compSize.height - scrollableRect.Height())),
190 compSize.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()
207 * for that.)
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);
223 return size;
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
254 * scrollable region.
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);
265 public:
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
472 // the frame delay).
473 // Modifies |aLayoutViewport| to continue enclosing |aVisualViewport|
474 // if possible.
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
477 // constraint.
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);
491 private:
492 // A ID assigned to each scrollable frame, unique within each LayersId..
493 ViewID mScrollId;
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
528 // remove this.
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
573 // resolution.
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
598 // the APZC.
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
621 // are the same.
623 // For a scroll frame that is not an RSF, this metric is meaningless and
624 // invalid.
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
653 // height.
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;
676 // WARNING!!!!
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
684 // (as needed):
685 // FrameMetrics::operator ==
686 // AsyncPanZoomController::NotifyLayersUpdated
687 // The ParamTraits specialization in LayersMessageUtils.h
689 // Please add new fields above this comment.
692 // clang-format off
693 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
694 OverscrollBehavior, uint8_t, (
695 Auto,
696 Contain,
697 None
699 // clang-format on
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;
745 public:
746 static StaticAutoPtr<const ScrollMetadata>
747 sNullMetadata; // We sometimes need an empty metadata
749 ScrollMetadata()
750 : mScrollParentId(ScrollableLayerGuid::NULL_SCROLL_ID),
751 mLineScrollAmount(0, 0),
752 mPageScrollAmount(0, 0),
753 mInteractiveWidget(
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 {
797 ScrollMetadata def;
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; }
885 private:
886 // For use in IPC only
887 void SetDidContentGetPainted(bool aValue) { mDidContentGetPainted = aValue; }
889 public:
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);
933 private:
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
940 // off.
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
979 // scrollframe.
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;
1038 // WARNING!!!!
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>>
1051 ScrollUpdatesMap;
1053 } // namespace layers
1054 } // namespace mozilla
1056 #endif /* GFX_FRAMEMETRICS_H */