Bug 1791375 - Switch ResizeObserver APIs to using an array of sizes. r=emilio

This is in preparation of supporting multiple fragments, since we should
track each fragment size separately.

This patch should have no observable effect.

Differential Revision: https://phabricator.services.mozilla.com/D157640
This commit is contained in:
Oriol Brufau 2022-09-21 20:19:55 +00:00
parent 0b1bad6f6b
commit 13f2137f7d
2 changed files with 61 additions and 43 deletions

View File

@ -73,12 +73,12 @@ static nsSize GetContentRectSize(const nsIFrame& aFrame) {
* *
* https://www.w3.org/TR/resize-observer-1/#calculate-box-size * https://www.w3.org/TR/resize-observer-1/#calculate-box-size
*/ */
static LogicalPixelSize CalculateBoxSize(Element* aTarget, static AutoTArray<LogicalPixelSize, 1> CalculateBoxSize(
ResizeObserverBoxOptions aBox) { Element* aTarget, ResizeObserverBoxOptions aBox) {
nsIFrame* frame = aTarget->GetPrimaryFrame(); nsIFrame* frame = aTarget->GetPrimaryFrame();
if (!frame) { if (!frame) {
return LogicalPixelSize(); return {LogicalPixelSize()};
} }
if (frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) { if (frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
@ -97,9 +97,9 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
const LayoutDeviceIntSize snappedSize = const LayoutDeviceIntSize snappedSize =
RoundedToInt(CSSSize::FromUnknownSize(size) * RoundedToInt(CSSSize::FromUnknownSize(size) *
frame->PresContext()->CSSToDevPixelScale()); frame->PresContext()->CSSToDevPixelScale());
return LogicalPixelSize(wm, gfx::Size(snappedSize.ToUnknownSize())); return {LogicalPixelSize(wm, gfx::Size(snappedSize.ToUnknownSize()))};
} }
return LogicalPixelSize(wm, size); return {LogicalPixelSize(wm, size)};
} }
// Per the spec, non-replaced inline Elements will always have an empty // Per the spec, non-replaced inline Elements will always have an empty
@ -108,7 +108,7 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
// always return false. (So its observation won't be fired.) // always return false. (So its observation won't be fired.)
if (!frame->IsFrameOfType(nsIFrame::eReplaced) && if (!frame->IsFrameOfType(nsIFrame::eReplaced) &&
frame->IsFrameOfType(nsIFrame::eLineParticipant)) { frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
return LogicalPixelSize(); return {LogicalPixelSize()};
} }
auto GetFrameSize = [&](nsIFrame* aFrame) { auto GetFrameSize = [&](nsIFrame* aFrame) {
@ -151,7 +151,7 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
} }
return CSSPixel::FromAppUnits(GetContentRectSize(*frame)).ToUnknownSize(); return CSSPixel::FromAppUnits(GetContentRectSize(*frame)).ToUnknownSize();
}; };
return LogicalPixelSize(frame->GetWritingMode(), GetFrameSize(frame)); return {LogicalPixelSize(frame->GetWritingMode(), GetFrameSize(frame))};
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObservation) NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObservation)
@ -174,9 +174,9 @@ ResizeObservation::ResizeObservation(Element& aTarget,
mObserver(&aObserver), mObserver(&aObserver),
mObservedBox(aBox), mObservedBox(aBox),
mLastReportedSize( mLastReportedSize(
StaticPrefs::dom_resize_observer_last_reported_size_invalid() {StaticPrefs::dom_resize_observer_last_reported_size_invalid()
? LogicalPixelSize(WritingMode(), gfx::Size(-1, -1)) ? LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))
: LogicalPixelSize()) { : LogicalPixelSize()}) {
aTarget.BindObject(mObserver); aTarget.BindObject(mObserver);
} }
@ -202,8 +202,9 @@ bool ResizeObservation::IsActive() const {
return mLastReportedSize != CalculateBoxSize(mTarget, mObservedBox); return mLastReportedSize != CalculateBoxSize(mTarget, mObservedBox);
} }
void ResizeObservation::UpdateLastReportedSize(const LogicalPixelSize& aSize) { void ResizeObservation::UpdateLastReportedSize(
mLastReportedSize = aSize; const nsTArray<LogicalPixelSize>& aSize) {
mLastReportedSize.Assign(aSize);
} }
// Only needed for refcounted objects. // Only needed for refcounted objects.
@ -309,7 +310,7 @@ void ResizeObserver::Observe(Element& aTarget,
// the general case, then we won't need this hack for the last remembered // the general case, then we won't need this hack for the last remembered
// size, and will have consistency with IntersectionObserver. // size, and will have consistency with IntersectionObserver.
observation->UpdateLastReportedSize( observation->UpdateLastReportedSize(
LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))); {LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))});
MOZ_ASSERT(observation->IsActive()); MOZ_ASSERT(observation->IsActive());
} }
mObservationList.insertBack(observation); mObservationList.insertBack(observation);
@ -381,11 +382,11 @@ uint32_t ResizeObserver::BroadcastActiveObservations() {
for (auto& observation : mActiveTargets) { for (auto& observation : mActiveTargets) {
Element* target = observation->Target(); Element* target = observation->Target();
LogicalPixelSize borderBoxSize = auto borderBoxSize =
CalculateBoxSize(target, ResizeObserverBoxOptions::Border_box); CalculateBoxSize(target, ResizeObserverBoxOptions::Border_box);
LogicalPixelSize contentBoxSize = auto contentBoxSize =
CalculateBoxSize(target, ResizeObserverBoxOptions::Content_box); CalculateBoxSize(target, ResizeObserverBoxOptions::Content_box);
LogicalPixelSize devicePixelContentBoxSize = CalculateBoxSize( auto devicePixelContentBoxSize = CalculateBoxSize(
target, ResizeObserverBoxOptions::Device_pixel_content_box); target, ResizeObserverBoxOptions::Device_pixel_content_box);
RefPtr<ResizeObserverEntry> entry = RefPtr<ResizeObserverEntry> entry =
new ResizeObserverEntry(mOwner, *target, borderBoxSize, contentBoxSize, new ResizeObserverEntry(mOwner, *target, borderBoxSize, contentBoxSize,
@ -450,8 +451,7 @@ void ResizeObserverEntry::GetBorderBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple // Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios. // fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface // https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear(); aRetVal.Assign(mBorderBoxSize);
aRetVal.AppendElement(mBorderBoxSize);
} }
void ResizeObserverEntry::GetContentBoxSize( void ResizeObserverEntry::GetContentBoxSize(
@ -462,8 +462,7 @@ void ResizeObserverEntry::GetContentBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple // Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios. // fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface // https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear(); aRetVal.Assign(mContentBoxSize);
aRetVal.AppendElement(mContentBoxSize);
} }
void ResizeObserverEntry::GetDevicePixelContentBoxSize( void ResizeObserverEntry::GetDevicePixelContentBoxSize(
@ -474,23 +473,32 @@ void ResizeObserverEntry::GetDevicePixelContentBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple // Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios. // fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface // https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear(); aRetVal.Assign(mDevicePixelContentBoxSize);
aRetVal.AppendElement(mDevicePixelContentBoxSize);
} }
void ResizeObserverEntry::SetBorderBoxSize(const LogicalPixelSize& aSize) { void ResizeObserverEntry::SetBorderBoxSize(
mBorderBoxSize = new ResizeObserverSize(mOwner, aSize); const nsTArray<LogicalPixelSize>& aSize) {
mBorderBoxSize.Clear();
mBorderBoxSize.SetCapacity(aSize.Length());
for (const LogicalPixelSize& size : aSize) {
mBorderBoxSize.AppendElement(new ResizeObserverSize(mOwner, size));
}
} }
void ResizeObserverEntry::SetContentRectAndSize(const LogicalPixelSize& aSize) { void ResizeObserverEntry::SetContentRectAndSize(
const nsTArray<LogicalPixelSize>& aSize) {
nsIFrame* frame = mTarget->GetPrimaryFrame(); nsIFrame* frame = mTarget->GetPrimaryFrame();
// 1. Update mContentRect. // 1. Update mContentRect.
nsMargin padding = frame ? frame->GetUsedPadding() : nsMargin(); nsMargin padding = frame ? frame->GetUsedPadding() : nsMargin();
// Per the spec, we need to use the top-left padding offset as the origin of // Per the spec, we need to use the top-left padding offset as the origin of
// our contentRect. // our contentRect.
const WritingMode wm = frame ? frame->GetWritingMode() : WritingMode(); gfx::Size sizeForRect;
gfx::Size sizeForRect = aSize.PhysicalSize(wm); MOZ_DIAGNOSTIC_ASSERT(!aSize.IsEmpty());
if (!aSize.IsEmpty()) {
const WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
sizeForRect = aSize[0].PhysicalSize(wm);
}
nsRect rect(nsPoint(padding.left, padding.top), nsRect rect(nsPoint(padding.left, padding.top),
CSSPixel::ToAppUnits(CSSSize::FromUnknownSize(sizeForRect))); CSSPixel::ToAppUnits(CSSSize::FromUnknownSize(sizeForRect)));
RefPtr<DOMRect> contentRect = new DOMRect(mOwner); RefPtr<DOMRect> contentRect = new DOMRect(mOwner);
@ -498,12 +506,21 @@ void ResizeObserverEntry::SetContentRectAndSize(const LogicalPixelSize& aSize) {
mContentRect = std::move(contentRect); mContentRect = std::move(contentRect);
// 2. Update mContentBoxSize. // 2. Update mContentBoxSize.
mContentBoxSize = new ResizeObserverSize(mOwner, aSize); mContentBoxSize.Clear();
mContentBoxSize.SetCapacity(aSize.Length());
for (const LogicalPixelSize& size : aSize) {
mContentBoxSize.AppendElement(new ResizeObserverSize(mOwner, size));
}
} }
void ResizeObserverEntry::SetDevicePixelContentSize( void ResizeObserverEntry::SetDevicePixelContentSize(
const LogicalPixelSize& aSize) { const nsTArray<LogicalPixelSize>& aSize) {
mDevicePixelContentBoxSize = new ResizeObserverSize(mOwner, aSize); mDevicePixelContentBoxSize.Clear();
mDevicePixelContentBoxSize.SetCapacity(aSize.Length());
for (const LogicalPixelSize& size : aSize) {
mDevicePixelContentBoxSize.AppendElement(
new ResizeObserverSize(mOwner, size));
}
} }
static void LastRememberedSizeCallback( static void LastRememberedSizeCallback(

View File

@ -93,9 +93,9 @@ class ResizeObservation final : public LinkedListElement<ResizeObservation> {
bool IsActive() const; bool IsActive() const;
/** /**
* Update current mLastReportedSize with size from aSize. * Update current mLastReportedSize to aSize.
*/ */
void UpdateLastReportedSize(const LogicalPixelSize& aSize); void UpdateLastReportedSize(const nsTArray<LogicalPixelSize>& aSize);
enum class RemoveFromObserver : bool { No, Yes }; enum class RemoveFromObserver : bool { No, Yes };
void Unlink(RemoveFromObserver); void Unlink(RemoveFromObserver);
@ -113,7 +113,7 @@ class ResizeObservation final : public LinkedListElement<ResizeObservation> {
// The latest recorded of observed target. // The latest recorded of observed target.
// This will be CSS pixels for border-box/content-box, or device pixels for // This will be CSS pixels for border-box/content-box, or device pixels for
// device-pixel-content-box. // device-pixel-content-box.
LogicalPixelSize mLastReportedSize; AutoTArray<LogicalPixelSize, 1> mLastReportedSize;
}; };
/** /**
@ -228,10 +228,11 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ResizeObserverEntry) NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ResizeObserverEntry)
ResizeObserverEntry(nsISupports* aOwner, Element& aTarget, ResizeObserverEntry(
const LogicalPixelSize& aBorderBoxSize, nsISupports* aOwner, Element& aTarget,
const LogicalPixelSize& aContentBoxSize, const nsTArray<LogicalPixelSize>& aBorderBoxSize,
const LogicalPixelSize& aDevicePixelContentBoxSize) const nsTArray<LogicalPixelSize>& aContentBoxSize,
const nsTArray<LogicalPixelSize>& aDevicePixelContentBoxSize)
: mOwner(aOwner), mTarget(&aTarget) { : mOwner(aOwner), mTarget(&aTarget) {
MOZ_ASSERT(mOwner, "Need a non-null owner"); MOZ_ASSERT(mOwner, "Need a non-null owner");
MOZ_ASSERT(mTarget, "Need a non-null target element"); MOZ_ASSERT(mTarget, "Need a non-null target element");
@ -269,19 +270,19 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
~ResizeObserverEntry() = default; ~ResizeObserverEntry() = default;
// Set borderBoxSize. // Set borderBoxSize.
void SetBorderBoxSize(const LogicalPixelSize& aSize); void SetBorderBoxSize(const nsTArray<LogicalPixelSize>& aSize);
// Set contentRect and contentBoxSize. // Set contentRect and contentBoxSize.
void SetContentRectAndSize(const LogicalPixelSize& aSize); void SetContentRectAndSize(const nsTArray<LogicalPixelSize>& aSize);
// Set devicePixelContentBoxSize. // Set devicePixelContentBoxSize.
void SetDevicePixelContentSize(const LogicalPixelSize& aSize); void SetDevicePixelContentSize(const nsTArray<LogicalPixelSize>& aSize);
nsCOMPtr<nsISupports> mOwner; nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<Element> mTarget; nsCOMPtr<Element> mTarget;
RefPtr<DOMRectReadOnly> mContentRect; RefPtr<DOMRectReadOnly> mContentRect;
RefPtr<ResizeObserverSize> mBorderBoxSize; AutoTArray<RefPtr<ResizeObserverSize>, 1> mBorderBoxSize;
RefPtr<ResizeObserverSize> mContentBoxSize; AutoTArray<RefPtr<ResizeObserverSize>, 1> mContentBoxSize;
RefPtr<ResizeObserverSize> mDevicePixelContentBoxSize; AutoTArray<RefPtr<ResizeObserverSize>, 1> mDevicePixelContentBoxSize;
}; };
class ResizeObserverSize final : public nsISupports, public nsWrapperCache { class ResizeObserverSize final : public nsISupports, public nsWrapperCache {