Commit 533d95e8 authored by Stefan Zager's avatar Stefan Zager Committed by Commit Bot

[IntersectionObserverV2] Add feature plumbing

BUG=827639
R=chrishtr@chromium.org

Change-Id: I21f63aed1e3bac1cae3e5ec0f9253371508579f4
Reviewed-on: https://chromium-review.googlesource.com/1050695
Commit-Queue: Stefan Zager <szager@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557045}
parent 7ebafc69
......@@ -18,6 +18,7 @@ IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
// Note that the spec says the initial value of m_lastThresholdIndex
// should be -1, but since m_lastThresholdIndex is unsigned, we use a
// different sentinel value.
last_is_visible_(false),
last_threshold_index_(kMaxThresholdIndex - 1) {
UpdateShouldReportRootBoundsAfterDomChange();
}
......@@ -72,16 +73,24 @@ void IntersectionObservation::ComputeIntersectionObservations(
// TODO(tkent): We can't use CHECK_LT due to a compile error.
CHECK(new_threshold_index < kMaxThresholdIndex);
if (last_threshold_index_ != new_threshold_index) {
bool is_visible = false;
if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled() &&
Observer()->trackVisibility()) {
// TODO(szager): Determine visibility.
}
if (last_threshold_index_ != new_threshold_index ||
last_is_visible_ != is_visible) {
FloatRect snapped_root_bounds(geometry.RootRect());
FloatRect* root_bounds_pointer =
should_report_root_bounds_ ? &snapped_root_bounds : nullptr;
IntersectionObserverEntry* new_entry = new IntersectionObserverEntry(
timestamp, new_visible_ratio, FloatRect(geometry.TargetRect()),
root_bounds_pointer, FloatRect(geometry.IntersectionRect()),
geometry.DoesIntersect(), Target());
geometry.DoesIntersect(), is_visible, Target());
Observer()->EnqueueIntersectionObserverEntry(*new_entry);
SetLastThresholdIndex(new_threshold_index);
SetWasVisible(is_visible);
}
}
......
......@@ -33,14 +33,17 @@ class IntersectionObservation final
private:
void SetLastThresholdIndex(unsigned index) { last_threshold_index_ = index; }
void SetWasVisible(bool last_is_visible) {
last_is_visible_ = last_is_visible ? 1 : 0;
}
Member<IntersectionObserver> observer_;
WeakMember<Element> target_;
unsigned should_report_root_bounds_ : 1;
unsigned last_threshold_index_ : 30;
static const unsigned kMaxThresholdIndex = (unsigned)0x40000000;
unsigned last_is_visible_ : 1;
unsigned last_threshold_index_ : 29;
static const unsigned kMaxThresholdIndex = (unsigned)0x20000000;
};
} // namespace blink
......
......@@ -150,7 +150,12 @@ IntersectionObserver* IntersectionObserver::Create(
if (exception_state.HadException())
return nullptr;
return new IntersectionObserver(delegate, root, root_margin, thresholds);
bool track_visibility = false;
if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled())
track_visibility = observer_init.trackVisibility();
return new IntersectionObserver(delegate, root, root_margin, thresholds,
track_visibility);
}
IntersectionObserver* IntersectionObserver::Create(
......@@ -168,18 +173,20 @@ IntersectionObserver* IntersectionObserver::Create(
const Vector<float>& thresholds,
Document* document,
EventCallback callback,
bool track_visibility,
ExceptionState& exception_state) {
IntersectionObserverDelegateImpl* intersection_observer_delegate =
new IntersectionObserverDelegateImpl(document, std::move(callback));
return new IntersectionObserver(*intersection_observer_delegate, nullptr,
root_margin, thresholds);
root_margin, thresholds, track_visibility);
}
IntersectionObserver::IntersectionObserver(
IntersectionObserverDelegate& delegate,
Element* root,
const Vector<Length>& root_margin,
const Vector<float>& thresholds)
const Vector<float>& thresholds,
bool track_visibility)
: ContextClient(delegate.GetExecutionContext()),
delegate_(&delegate),
root_(root),
......@@ -188,7 +195,8 @@ IntersectionObserver::IntersectionObserver(
right_margin_(kFixed),
bottom_margin_(kFixed),
left_margin_(kFixed),
root_is_implicit_(root ? 0 : 1) {
root_is_implicit_(root ? 0 : 1),
track_visibility_(track_visibility ? 1 : 0) {
switch (root_margin.size()) {
case 0:
break;
......
......@@ -50,6 +50,7 @@ class CORE_EXPORT IntersectionObserver final
const Vector<float>& thresholds,
Document*,
EventCallback,
bool track_visbility = false,
ExceptionState& = ASSERT_NO_EXCEPTION);
static void ResumeSuspendedObservers();
......@@ -63,6 +64,7 @@ class CORE_EXPORT IntersectionObserver final
Element* root() const { return root_.Get(); }
String rootMargin() const;
const Vector<float>& thresholds() const { return thresholds_; }
bool trackVisibility() const { return track_visibility_; }
// An observer can either track intersections with an explicit root Element,
// or with the the top-level frame's viewport (the "implicit root"). When
......@@ -100,7 +102,8 @@ class CORE_EXPORT IntersectionObserver final
explicit IntersectionObserver(IntersectionObserverDelegate&,
Element*,
const Vector<Length>& root_margin,
const Vector<float>& thresholds);
const Vector<float>& thresholds,
bool track_visibility);
void ClearWeakMembers(Visitor*);
// Returns false if this observer has an explicit root element which has been
......@@ -117,6 +120,7 @@ class CORE_EXPORT IntersectionObserver final
Length bottom_margin_;
Length left_margin_;
unsigned root_is_implicit_ : 1;
unsigned track_visibility_ : 1;
};
} // namespace blink
......
......@@ -19,6 +19,7 @@ callback IntersectionObserverCallback = void (sequence<IntersectionObserverEntry
readonly attribute DOMString rootMargin;
// https://github.com/WICG/IntersectionObserver/issues/114
readonly attribute FrozenArray<double> thresholds;
[RuntimeEnabled=IntersectionObserverV2] readonly attribute boolean trackVisibility;
[RaisesException] void observe(Element target);
[RaisesException] void unobserve(Element target);
[RaisesException] void disconnect();
......
......@@ -15,6 +15,7 @@ IntersectionObserverEntry::IntersectionObserverEntry(
const FloatRect* root_bounds,
const FloatRect& intersection_rect,
bool is_intersecting,
bool is_visible,
Element* target)
: time_(time),
intersection_ratio_(intersection_ratio),
......@@ -24,7 +25,8 @@ IntersectionObserverEntry::IntersectionObserverEntry(
: nullptr),
intersection_rect_(DOMRectReadOnly::FromFloatRect(intersection_rect)),
target_(target),
is_intersecting_(is_intersecting)
is_intersecting_(is_intersecting),
is_visible_(is_visible)
{}
......
......@@ -25,6 +25,7 @@ class IntersectionObserverEntry final : public ScriptWrappable {
const FloatRect* root_bounds,
const FloatRect& intersection_rect,
bool is_intersecting,
bool is_visible,
Element*);
double time() const { return time_; }
......@@ -33,6 +34,7 @@ class IntersectionObserverEntry final : public ScriptWrappable {
DOMRectReadOnly* rootBounds() const { return root_bounds_; }
DOMRectReadOnly* intersectionRect() const { return intersection_rect_; }
bool isIntersecting() const { return is_intersecting_; }
bool isVisible() const { return is_visible_; }
Element* target() const { return target_.Get(); }
void Trace(blink::Visitor*) override;
......@@ -45,6 +47,7 @@ class IntersectionObserverEntry final : public ScriptWrappable {
Member<DOMRectReadOnly> intersection_rect_;
Member<Element> target_;
bool is_intersecting_;
bool is_visible_;
};
} // namespace blink
......
......@@ -11,6 +11,7 @@ interface IntersectionObserverEntry {
readonly attribute DOMRectReadOnly boundingClientRect;
readonly attribute DOMRectReadOnly intersectionRect;
readonly attribute boolean isIntersecting;
[RuntimeEnabled=IntersectionObserverV2] readonly attribute boolean isVisible;
readonly attribute double intersectionRatio;
readonly attribute Element target;
};
......@@ -8,4 +8,5 @@ dictionary IntersectionObserverInit {
Element? root = null;
DOMString rootMargin = "0px";
(double or sequence<double>) threshold = 0;
[RuntimeEnabled=IntersectionObserverV2] boolean trackVisibility = false;
};
......@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
......@@ -234,4 +235,19 @@ TEST_F(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) {
EXPECT_TRUE(observer_delegate->LastIntersectionRect().IsEmpty());
}
TEST_F(IntersectionObserverTest, TrackVisibilityInit) {
ScopedIntersectionObserverV2ForTest iov2_enabled(true);
IntersectionObserverInit observer_init;
DummyExceptionStateForTesting exception_state;
TestIntersectionObserverDelegate* observer_delegate =
new TestIntersectionObserverDelegate(GetDocument());
IntersectionObserver* observer = IntersectionObserver::Create(
observer_init, *observer_delegate, exception_state);
EXPECT_FALSE(observer->trackVisibility());
observer_init.setTrackVisibility(true);
observer = IntersectionObserver::Create(observer_init, *observer_delegate,
exception_state);
EXPECT_TRUE(observer->trackVisibility());
}
} // namespace blink
......@@ -615,6 +615,9 @@
origin_trial_feature_name: "InstalledApp",
status: "experimental",
},
{
name: "IntersectionObserverV2",
},
{
name: "JSImageDecode",
status: "stable",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment