mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1798485 - Add support for the contentvisibilityautostatechange
event r=emilio
Add support for the contentvisibilityautostatechange and fire it when the relevancy of `content-visibility: auto` elements change. This commit also makes some changes to the content-visibility-auto-state-changed.html test. Two more subtests are added which verifies that an event is sent after `content-visibility: auto` is applied to an element. Finally the `top` element is renamed to `upper` as `top` can also refer to the top-level Window and it seems that Gecko has a different precedence when accessing variables in script. Differential Revision: https://phabricator.services.mozilla.com/D161140
This commit is contained in:
parent
812f4325ff
commit
97f351c1d4
18
dom/webidl/ContentVisibilityAutoStateChangeEvent.webidl
Normal file
18
dom/webidl/ContentVisibilityAutoStateChangeEvent.webidl
Normal file
@ -0,0 +1,18 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* https://drafts.csswg.org/css-contain-2/#content-visibility-auto-state-changed
|
||||
*/
|
||||
|
||||
[Exposed=Window, Pref="layout.css.content-visibility.enabled"]
|
||||
interface ContentVisibilityAutoStateChangeEvent : Event {
|
||||
constructor(DOMString type,
|
||||
optional ContentVisibilityAutoStateChangeEventInit eventInitDict = {});
|
||||
readonly attribute boolean skipped;
|
||||
};
|
||||
|
||||
dictionary ContentVisibilityAutoStateChangeEventInit : EventInit {
|
||||
boolean skipped = false;
|
||||
};
|
@ -1147,6 +1147,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
"BlobEvent.webidl",
|
||||
"CaretStateChangedEvent.webidl",
|
||||
"CloseEvent.webidl",
|
||||
"ContentVisibilityAutoStateChangeEvent.webidl",
|
||||
"DeviceLightEvent.webidl",
|
||||
"DeviceOrientationEvent.webidl",
|
||||
"ErrorEvent.webidl",
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mozilla/DisplayPortUtils.h"
|
||||
#include "mozilla/dom/CSSAnimation.h"
|
||||
#include "mozilla/dom/CSSTransition.h"
|
||||
#include "mozilla/dom/ContentVisibilityAutoStateChangeEvent.h"
|
||||
#include "mozilla/dom/DocumentInlines.h"
|
||||
#include "mozilla/dom/AncestorIterator.h"
|
||||
#include "mozilla/dom/ElementInlines.h"
|
||||
@ -7053,12 +7054,29 @@ void nsIFrame::UpdateIsRelevantContent(
|
||||
element->SetContentRelevancy(newRelevancy);
|
||||
}
|
||||
|
||||
if (overallRelevancyChanged) {
|
||||
HandleLastRememberedSize();
|
||||
PresShell()->FrameNeedsReflow(
|
||||
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
|
||||
InvalidateFrame();
|
||||
if (!overallRelevancyChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
HandleLastRememberedSize();
|
||||
PresShell()->FrameNeedsReflow(
|
||||
this, IntrinsicDirty::FrameAncestorsAndDescendants, NS_FRAME_IS_DIRTY);
|
||||
InvalidateFrame();
|
||||
|
||||
ContentVisibilityAutoStateChangeEventInit init;
|
||||
init.mSkipped = newRelevancy.isEmpty();
|
||||
RefPtr<ContentVisibilityAutoStateChangeEvent> event =
|
||||
ContentVisibilityAutoStateChangeEvent::Constructor(
|
||||
element, u"contentvisibilityautostatechange"_ns, init);
|
||||
|
||||
// Per
|
||||
// https://drafts.csswg.org/css-contain/#content-visibility-auto-state-changed
|
||||
// "This event is dispatched by posting a task at the time when the state
|
||||
// change occurs."
|
||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(element, event.get());
|
||||
DebugOnly<nsresult> rv = asyncDispatcher->PostDOMEvent();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "AsyncEventDispatcher failed to dispatch");
|
||||
}
|
||||
|
||||
nsresult nsIFrame::CharacterDataChanged(const CharacterDataChangeInfo&) {
|
||||
|
@ -1,7 +0,0 @@
|
||||
[content-visibility-auto-state-changed.html]
|
||||
expected: TIMEOUT
|
||||
[ContentVisibilityAutoStateChange fires when skipped]
|
||||
expected: TIMEOUT
|
||||
|
||||
[ContentVisibilityAutoStateChange fires when not skipped]
|
||||
expected: NOTRUN
|
@ -21,24 +21,52 @@
|
||||
.auto { content-visibility: auto; }
|
||||
</style>
|
||||
|
||||
<div id=top class=auto></div>
|
||||
<div id=upper></div>
|
||||
<div class=spacer></div>
|
||||
<div id=middle></div>
|
||||
<div class=spacer></div>
|
||||
<div id=bottom class=auto></div>
|
||||
<div id=lower></div>
|
||||
|
||||
<script>
|
||||
promise_test(t => new Promise(async (resolve, reject) => {
|
||||
let shouldSkip = false;
|
||||
const listener = (e) => {
|
||||
if (!e.skipped)
|
||||
resolve();
|
||||
};
|
||||
|
||||
upper.addEventListener("contentvisibilityautostatechange", listener);
|
||||
t.add_cleanup(() => upper.removeEventListener("contentvisibilityautostatechange", listener));
|
||||
upper.classList.add("auto");
|
||||
}), "ContentVisibilityAutoStateChange fires when relevant element gains `content-visibility:auto`");
|
||||
|
||||
promise_test(t => new Promise(async (resolve, reject) => {
|
||||
let shouldSkip = false;
|
||||
const listener = (e) => {
|
||||
if (e.skipped)
|
||||
resolve();
|
||||
else
|
||||
reject();
|
||||
};
|
||||
|
||||
lower.addEventListener("contentvisibilityautostatechange", listener);
|
||||
t.add_cleanup(() => lower.removeEventListener("contentvisibilityautostatechange", listener));
|
||||
lower.classList.add("auto");
|
||||
}), "ContentVisibilityAutoStateChange fires when not relevant element gains `content-visibility:auto`");
|
||||
|
||||
promise_test(t => new Promise(async (resolve, reject) => {
|
||||
await new Promise((waited, _) => {
|
||||
requestAnimationFrame(() => requestAnimationFrame(waited));
|
||||
});
|
||||
|
||||
top.addEventListener("contentvisibilityautostatechange", (e) => {
|
||||
const listener = (e) => {
|
||||
if (e.skipped)
|
||||
resolve();
|
||||
else
|
||||
reject();
|
||||
});
|
||||
};
|
||||
|
||||
upper.addEventListener("contentvisibilityautostatechange", listener);
|
||||
t.add_cleanup(() => upper.removeEventListener("contentvisibilityautostatechange", listener));
|
||||
|
||||
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||
middle.scrollIntoView();
|
||||
}));
|
||||
@ -49,15 +77,22 @@ promise_test(t => new Promise(async (resolve, reject) => {
|
||||
requestAnimationFrame(() => requestAnimationFrame(waited));
|
||||
});
|
||||
|
||||
bottom.addEventListener("contentvisibilityautostatechange", (e) => {
|
||||
const listener = (e) => {
|
||||
if (!e.skipped)
|
||||
resolve();
|
||||
else
|
||||
reject();
|
||||
}
|
||||
|
||||
lower.addEventListener("contentvisibilityautostatechange", listener);
|
||||
t.add_cleanup(() => {
|
||||
lower.removeEventListener("contentvisibilityautostatechange", listener);
|
||||
});
|
||||
|
||||
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||
bottom.scrollIntoView();
|
||||
lower.scrollIntoView();
|
||||
}));
|
||||
}), "ContentVisibilityAutoStateChange fires when not skipped");
|
||||
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user