Skip to content

Commit

Permalink
Bug 1791375 - Switch ResizeObserver APIs to using an array of sizes. …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Loirooriol committed Sep 21, 2022
1 parent ac52d72 commit 2f8e897
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 43 deletions.
77 changes: 47 additions & 30 deletions dom/base/ResizeObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ static nsSize GetContentRectSize(const nsIFrame& aFrame) {
*
* https://www.w3.org/TR/resize-observer-1/#calculate-box-size
*/
static LogicalPixelSize CalculateBoxSize(Element* aTarget,
ResizeObserverBoxOptions aBox) {
static AutoTArray<LogicalPixelSize, 1> CalculateBoxSize(
Element* aTarget, ResizeObserverBoxOptions aBox) {
nsIFrame* frame = aTarget->GetPrimaryFrame();

if (!frame) {
return LogicalPixelSize();
return {LogicalPixelSize()};
}

if (frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
Expand All @@ -97,9 +97,9 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
const LayoutDeviceIntSize snappedSize =
RoundedToInt(CSSSize::FromUnknownSize(size) *
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
Expand All @@ -108,7 +108,7 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
// always return false. (So its observation won't be fired.)
if (!frame->IsFrameOfType(nsIFrame::eReplaced) &&
frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
return LogicalPixelSize();
return {LogicalPixelSize()};
}

auto GetFrameSize = [&](nsIFrame* aFrame) {
Expand Down Expand Up @@ -151,7 +151,7 @@ static LogicalPixelSize CalculateBoxSize(Element* aTarget,
}
return CSSPixel::FromAppUnits(GetContentRectSize(*frame)).ToUnknownSize();
};
return LogicalPixelSize(frame->GetWritingMode(), GetFrameSize(frame));
return {LogicalPixelSize(frame->GetWritingMode(), GetFrameSize(frame))};
}

NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObservation)
Expand All @@ -174,9 +174,9 @@ ResizeObservation::ResizeObservation(Element& aTarget,
mObserver(&aObserver),
mObservedBox(aBox),
mLastReportedSize(
StaticPrefs::dom_resize_observer_last_reported_size_invalid()
? LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))
: LogicalPixelSize()) {
{StaticPrefs::dom_resize_observer_last_reported_size_invalid()
? LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))
: LogicalPixelSize()}) {
aTarget.BindObject(mObserver);
}

Expand All @@ -202,8 +202,9 @@ bool ResizeObservation::IsActive() const {
return mLastReportedSize != CalculateBoxSize(mTarget, mObservedBox);
}

void ResizeObservation::UpdateLastReportedSize(const LogicalPixelSize& aSize) {
mLastReportedSize = aSize;
void ResizeObservation::UpdateLastReportedSize(
const nsTArray<LogicalPixelSize>& aSize) {
mLastReportedSize.Assign(aSize);
}

// Only needed for refcounted objects.
Expand Down Expand Up @@ -309,7 +310,7 @@ void ResizeObserver::Observe(Element& aTarget,
// the general case, then we won't need this hack for the last remembered
// size, and will have consistency with IntersectionObserver.
observation->UpdateLastReportedSize(
LogicalPixelSize(WritingMode(), gfx::Size(-1, -1)));
{LogicalPixelSize(WritingMode(), gfx::Size(-1, -1))});
MOZ_ASSERT(observation->IsActive());
}
mObservationList.insertBack(observation);
Expand Down Expand Up @@ -381,11 +382,11 @@ uint32_t ResizeObserver::BroadcastActiveObservations() {
for (auto& observation : mActiveTargets) {
Element* target = observation->Target();

LogicalPixelSize borderBoxSize =
auto borderBoxSize =
CalculateBoxSize(target, ResizeObserverBoxOptions::Border_box);
LogicalPixelSize contentBoxSize =
auto contentBoxSize =
CalculateBoxSize(target, ResizeObserverBoxOptions::Content_box);
LogicalPixelSize devicePixelContentBoxSize = CalculateBoxSize(
auto devicePixelContentBoxSize = CalculateBoxSize(
target, ResizeObserverBoxOptions::Device_pixel_content_box);
RefPtr<ResizeObserverEntry> entry =
new ResizeObserverEntry(mOwner, *target, borderBoxSize, contentBoxSize,
Expand Down Expand Up @@ -450,8 +451,7 @@ void ResizeObserverEntry::GetBorderBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear();
aRetVal.AppendElement(mBorderBoxSize);
aRetVal.Assign(mBorderBoxSize);
}

void ResizeObserverEntry::GetContentBoxSize(
Expand All @@ -462,8 +462,7 @@ void ResizeObserverEntry::GetContentBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear();
aRetVal.AppendElement(mContentBoxSize);
aRetVal.Assign(mContentBoxSize);
}

void ResizeObserverEntry::GetDevicePixelContentBoxSize(
Expand All @@ -474,36 +473,54 @@ void ResizeObserverEntry::GetDevicePixelContentBoxSize(
// Note: the usage of FrozenArray is to support elements that have multiple
// fragments, which occur in multi-column scenarios.
// https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface
aRetVal.Clear();
aRetVal.AppendElement(mDevicePixelContentBoxSize);
aRetVal.Assign(mDevicePixelContentBoxSize);
}

void ResizeObserverEntry::SetBorderBoxSize(const LogicalPixelSize& aSize) {
mBorderBoxSize = new ResizeObserverSize(mOwner, aSize);
void ResizeObserverEntry::SetBorderBoxSize(
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();

// 1. Update mContentRect.
nsMargin padding = frame ? frame->GetUsedPadding() : nsMargin();
// Per the spec, we need to use the top-left padding offset as the origin of
// our contentRect.
const WritingMode wm = frame ? frame->GetWritingMode() : WritingMode();
gfx::Size sizeForRect = aSize.PhysicalSize(wm);
gfx::Size sizeForRect;
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),
CSSPixel::ToAppUnits(CSSSize::FromUnknownSize(sizeForRect)));
RefPtr<DOMRect> contentRect = new DOMRect(mOwner);
contentRect->SetLayoutRect(rect);
mContentRect = std::move(contentRect);

// 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(
const LogicalPixelSize& aSize) {
mDevicePixelContentBoxSize = new ResizeObserverSize(mOwner, aSize);
const nsTArray<LogicalPixelSize>& aSize) {
mDevicePixelContentBoxSize.Clear();
mDevicePixelContentBoxSize.SetCapacity(aSize.Length());
for (const LogicalPixelSize& size : aSize) {
mDevicePixelContentBoxSize.AppendElement(
new ResizeObserverSize(mOwner, size));
}
}

static void LastRememberedSizeCallback(
Expand Down
27 changes: 14 additions & 13 deletions dom/base/ResizeObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class ResizeObservation final : public LinkedListElement<ResizeObservation> {
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 };
void Unlink(RemoveFromObserver);
Expand All @@ -113,7 +113,7 @@ class ResizeObservation final : public LinkedListElement<ResizeObservation> {
// The latest recorded of observed target.
// This will be CSS pixels for border-box/content-box, or device pixels for
// device-pixel-content-box.
LogicalPixelSize mLastReportedSize;
AutoTArray<LogicalPixelSize, 1> mLastReportedSize;
};

/**
Expand Down Expand Up @@ -228,10 +228,11 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ResizeObserverEntry)

ResizeObserverEntry(nsISupports* aOwner, Element& aTarget,
const LogicalPixelSize& aBorderBoxSize,
const LogicalPixelSize& aContentBoxSize,
const LogicalPixelSize& aDevicePixelContentBoxSize)
ResizeObserverEntry(
nsISupports* aOwner, Element& aTarget,
const nsTArray<LogicalPixelSize>& aBorderBoxSize,
const nsTArray<LogicalPixelSize>& aContentBoxSize,
const nsTArray<LogicalPixelSize>& aDevicePixelContentBoxSize)
: mOwner(aOwner), mTarget(&aTarget) {
MOZ_ASSERT(mOwner, "Need a non-null owner");
MOZ_ASSERT(mTarget, "Need a non-null target element");
Expand Down Expand Up @@ -269,19 +270,19 @@ class ResizeObserverEntry final : public nsISupports, public nsWrapperCache {
~ResizeObserverEntry() = default;

// Set borderBoxSize.
void SetBorderBoxSize(const LogicalPixelSize& aSize);
void SetBorderBoxSize(const nsTArray<LogicalPixelSize>& aSize);
// Set contentRect and contentBoxSize.
void SetContentRectAndSize(const LogicalPixelSize& aSize);
void SetContentRectAndSize(const nsTArray<LogicalPixelSize>& aSize);
// Set devicePixelContentBoxSize.
void SetDevicePixelContentSize(const LogicalPixelSize& aSize);
void SetDevicePixelContentSize(const nsTArray<LogicalPixelSize>& aSize);

nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<Element> mTarget;

RefPtr<DOMRectReadOnly> mContentRect;
RefPtr<ResizeObserverSize> mBorderBoxSize;
RefPtr<ResizeObserverSize> mContentBoxSize;
RefPtr<ResizeObserverSize> mDevicePixelContentBoxSize;
AutoTArray<RefPtr<ResizeObserverSize>, 1> mBorderBoxSize;
AutoTArray<RefPtr<ResizeObserverSize>, 1> mContentBoxSize;
AutoTArray<RefPtr<ResizeObserverSize>, 1> mDevicePixelContentBoxSize;
};

class ResizeObserverSize final : public nsISupports, public nsWrapperCache {
Expand Down

0 comments on commit 2f8e897

Please sign in to comment.