Skip to content

Commit

Permalink
[content-visibility] Improve skipped content information in RenderStyle
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=259042

Reviewed by Simon Fraser.

Improve skipped content information in RenderStyle because beside the fact that
something is skipped content we also want to know if the skipped content is in
a hidden or auto content-visibility subtree.

* LayoutTests/imported/w3c/web-platform-tests/css/css-contain/content-visibility/content-visibility-087-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-contain/content-visibility/content-visibility-087.html: Added.
* Source/WebCore/dom/Element.cpp:
(WebCore::Element::hasFocusableStyle const):
* Source/WebCore/rendering/RenderObject.cpp:
(WebCore::RenderObject::isSkippedContent const):
* Source/WebCore/rendering/style/RenderStyle.h:
* Source/WebCore/rendering/style/RenderStyleInlines.h:
(WebCore::RenderStyle::effectivePointerEvents const):
(WebCore::RenderStyle::skippedContentReason const):
(WebCore::RenderStyle::effectiveSkippedContent const): Deleted.
* Source/WebCore/rendering/style/RenderStyleSetters.h:
(WebCore::RenderStyle::setEffectiveInert):
(WebCore::RenderStyle::setSkippedContentReason):
(WebCore::RenderStyle::setEffectiveSkippedContent): Deleted.
* Source/WebCore/rendering/style/StyleRareInheritedData.cpp:
(WebCore::StyleRareInheritedData::StyleRareInheritedData):
* Source/WebCore/rendering/style/StyleRareInheritedData.h:
* Source/WebCore/rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::updateRenderTree):
(WebCore::RenderTreeUpdater::updateElementRenderer):
* Source/WebCore/style/StyleAdjuster.cpp:
(WebCore::Style::Adjuster::adjust const): c-v: hidden overrides auto as relevancy reason

Canonical link: https://commits.webkit.org/267128@main
  • Loading branch information
rwlbuis committed Aug 22, 2023
1 parent ffc701d commit 682cdce
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS Trying to focus on an element in a nested hidden/auto subtree will not work

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype HTML>
<html>
<meta charset="utf8">
<title>Content visibility: focus does not target nested c-v: hidden/auto subtree"</title>
<link rel="author" title="Rob Buis" href="mailto:rbuis@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
<meta name="assert" content="focus does not target nested c-v: hidden/auto subtree">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<div style="content-visibility: hidden">
<div style="content-visibility: auto">
<div id="focusable" tabIndex="0">
focusable thing
</div>
</div>
</div>

<script>
test(() => {
focusable.focus();
assert_not_equals(document.activeElement, focusable);
}, "Trying to focus on an element in a nested hidden/auto subtree will not work");
</script>
</html>
11 changes: 2 additions & 9 deletions Source/WebCore/dom/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,17 +769,10 @@ Vector<String> Element::getAttributeNames() const

bool Element::hasFocusableStyle() const
{
if (renderer() && renderer()->isSkippedContent()) {
auto* candidate = this;
while ((candidate = candidate->parentElementInComposedTree())) {
if (candidate->renderer() && candidate->renderStyle()->contentVisibility() == ContentVisibility::Hidden)
return false;
}
}

auto isFocusableStyle = [](const RenderStyle* style) {
return style && style->display() != DisplayType::None && style->display() != DisplayType::Contents
&& style->visibility() == Visibility::Visible && !style->effectiveInert();
&& style->visibility() == Visibility::Visible && !style->effectiveInert()
&& (style->skippedContentReason().value_or(ContentVisibility::Visible) != ContentVisibility::Hidden || style->contentVisibility() != ContentVisibility::Visible);
};

if (renderStyle())
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/RenderObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2677,7 +2677,7 @@ String RenderObject::debugDescription() const

bool RenderObject::isSkippedContent() const
{
return parent() && parent()->style().effectiveSkippedContent();
return parent() && parent()->style().skippedContentReason().has_value();
}

TextStream& operator<<(TextStream& ts, const RenderObject& renderer)
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/rendering/style/RenderStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ class RenderStyle {

inline ContentVisibility contentVisibility() const;

inline bool effectiveSkippedContent() const;
inline std::optional<ContentVisibility> skippedContentReason() const;

inline ContainIntrinsicSizeType containIntrinsicWidthType() const;
inline ContainIntrinsicSizeType containIntrinsicHeightType() const;
Expand Down Expand Up @@ -1278,7 +1278,7 @@ class RenderStyle {

inline void setContentVisibility(ContentVisibility);

inline void setEffectiveSkippedContent(bool);
inline void setSkippedContentReason(ContentVisibility);

inline void setListStyleType(ListStyleType);
void setListStyleImage(RefPtr<StyleImage>&&);
Expand Down
6 changes: 5 additions & 1 deletion Source/WebCore/rendering/style/RenderStyleInlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ inline StyleAppearance RenderStyle::effectiveAppearance() const { return static_
inline OptionSet<Containment> RenderStyle::effectiveContainment() const { return m_nonInheritedData->rareData->effectiveContainment(); }
inline bool RenderStyle::effectiveInert() const { return m_rareInheritedData->effectiveInert; }
inline PointerEvents RenderStyle::effectivePointerEvents() const { return effectiveInert() ? PointerEvents::None : pointerEvents(); }
inline bool RenderStyle::effectiveSkippedContent() const { return m_rareInheritedData->effectiveSkippedContent; }
inline CSSPropertyID RenderStyle::effectiveStrokeColorProperty() const { return hasExplicitlySetStrokeColor() ? CSSPropertyStrokeColor : CSSPropertyWebkitTextStrokeColor; }
inline OptionSet<TouchAction> RenderStyle::effectiveTouchActions() const { return m_rareInheritedData->effectiveTouchActions; }
inline UserModify RenderStyle::effectiveUserModify() const { return effectiveInert() ? UserModify::ReadOnly : userModify(); }
Expand Down Expand Up @@ -647,6 +646,11 @@ inline const StyleColor& RenderStyle::scrollbarTrackColor() const { return m_rar
inline float RenderStyle::shapeImageThreshold() const { return m_nonInheritedData->rareData->shapeImageThreshold; }
inline const Length& RenderStyle::shapeMargin() const { return m_nonInheritedData->rareData->shapeMargin; }
inline ShapeValue* RenderStyle::shapeOutside() const { return m_nonInheritedData->rareData->shapeOutside.get(); }
inline std::optional<ContentVisibility> RenderStyle::skippedContentReason() const
{
auto reason = static_cast<ContentVisibility>(m_rareInheritedData->effectiveSkippedContent);
return reason == ContentVisibility::Visible ? std::nullopt : std::optional { reason };
}
inline OptionSet<SpeakAs> RenderStyle::speakAs() const { return OptionSet<SpeakAs>::fromRaw(m_rareInheritedData->speakAs); }
inline const AtomString& RenderStyle::specifiedLocale() const { return fontDescription().specifiedLocale(); }
inline int RenderStyle::specifiedZIndex() const { return m_nonInheritedData->boxData->specifiedZIndex(); }
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/style/RenderStyleSetters.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ inline void RenderStyle::setContainerType(ContainerType type) { SET_NESTED(m_non
inline void RenderStyle::setContentVisibility(ContentVisibility value) { SET_NESTED(m_nonInheritedData, rareData, contentVisibility, static_cast<unsigned>(value)); }
inline void RenderStyle::setEffectiveAppearance(StyleAppearance a) { SET_NESTED(m_nonInheritedData, miscData, effectiveAppearance, static_cast<unsigned>(a)); }
inline void RenderStyle::setEffectiveInert(bool effectiveInert) { SET(m_rareInheritedData, effectiveInert, effectiveInert); }
inline void RenderStyle::setEffectiveSkippedContent(bool effectiveSkippedContent) { SET(m_rareInheritedData, effectiveSkippedContent, effectiveSkippedContent); }
inline void RenderStyle::setEffectiveTouchActions(OptionSet<TouchAction> touchActions) { SET(m_rareInheritedData, effectiveTouchActions, touchActions); }
inline void RenderStyle::setEventListenerRegionTypes(OptionSet<EventListenerRegionType> eventListenerTypes) { SET(m_rareInheritedData, eventListenerRegionTypes, eventListenerTypes); }
inline void RenderStyle::setFilter(const FilterOperations& ops) { SET_DOUBLY_NESTED(m_nonInheritedData, miscData, filter, operations, ops); }
Expand Down Expand Up @@ -277,6 +276,7 @@ inline void RenderStyle::setScrollbarColor(const std::optional<ScrollbarColor>&
inline void RenderStyle::setScrollbarThumbColor(const StyleColor& color) { m_rareInheritedData.access().scrollbarColor->thumbColor = color; }
inline void RenderStyle::setScrollbarTrackColor(const StyleColor& color) { m_rareInheritedData.access().scrollbarColor->trackColor = color; }
inline void RenderStyle::setShapeMargin(Length&& margin) { SET_NESTED(m_nonInheritedData, rareData, shapeMargin, WTFMove(margin)); }
inline void RenderStyle::setSkippedContentReason(ContentVisibility effectiveSkippedContent) { SET(m_rareInheritedData, effectiveSkippedContent, static_cast<unsigned>(effectiveSkippedContent)); }
inline void RenderStyle::setSpeakAs(OptionSet<SpeakAs> style) { SET(m_rareInheritedData, speakAs, style.toRaw()); }
inline void RenderStyle::setSpecifiedZIndex(int value) { SET_NESTED_PAIR(m_nonInheritedData, boxData, m_hasAutoSpecifiedZIndex, false, m_specifiedZIndex, value); }
inline void RenderStyle::setStrokeColor(const StyleColor& color) { SET(m_rareInheritedData, strokeColor, color); }
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/style/StyleRareInheritedData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ StyleRareInheritedData::StyleRareInheritedData()
, hasAutoAccentColor(true)
, effectiveInert(false)
, isInSubtreeWithBlendMode(false)
, effectiveSkippedContent(false)
, effectiveSkippedContent(static_cast<unsigned>(ContentVisibility::Visible))
, effectiveTouchActions(RenderStyle::initialTouchActions())
, strokeWidth(RenderStyle::initialStrokeWidth())
, strokeColor(RenderStyle::initialStrokeColor())
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/style/StyleRareInheritedData.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class StyleRareInheritedData : public RefCounted<StyleRareInheritedData> {

unsigned isInSubtreeWithBlendMode : 1;

unsigned effectiveSkippedContent : 1;
unsigned effectiveSkippedContent : 2; // ContentVisibility

OptionSet<TouchAction> effectiveTouchActions;
OptionSet<EventListenerRegionType> eventListenerRegionTypes;
Expand Down
6 changes: 3 additions & 3 deletions Source/WebCore/rendering/updating/RenderTreeUpdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ void RenderTreeUpdater::updateRenderTree(ContainerNode& root)

auto mayHaveRenderedDescendants = [&]() {
if (element.renderer())
return !(element.isInTopLayer() && element.renderer()->style().effectiveSkippedContent());
return !(element.isInTopLayer() && element.renderer()->isSkippedContent());
return element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent());
}();

Expand Down Expand Up @@ -324,7 +324,7 @@ void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::Ele
auto elementUpdateStyle = RenderStyle::cloneIncludingPseudoElements(*elementUpdate.style);

bool shouldTearDownRenderers = [&]() {
if (element.isInTopLayer() && elementUpdate.change == Style::Change::Inherited && elementUpdate.style->effectiveSkippedContent())
if (element.isInTopLayer() && elementUpdate.change == Style::Change::Inherited && elementUpdate.style->skippedContentReason().has_value())
return true;
return elementUpdate.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
}();
Expand Down Expand Up @@ -364,7 +364,7 @@ void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::Ele
}
});

bool shouldCreateNewRenderer = !element.renderer() && !hasDisplayContents && !(element.isInTopLayer() && renderTreePosition().parent().style().effectiveSkippedContent());
bool shouldCreateNewRenderer = !element.renderer() && !hasDisplayContents && !(element.isInTopLayer() && renderTreePosition().parent().style().skippedContentReason().has_value());
if (shouldCreateNewRenderer) {
if (element.hasCustomStyleResolveCallbacks())
element.willAttachRenderers();
Expand Down
5 changes: 2 additions & 3 deletions Source/WebCore/style/StyleAdjuster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,8 @@ void Adjuster::adjust(RenderStyle& style, const RenderStyle* userAgentAppearance
adjustForTextAutosizing(style, *m_element);
#endif
}

if (isSkippedContentRoot(style, m_element))
style.setEffectiveSkippedContent(true);
if (isSkippedContentRoot(style, m_element) && m_parentStyle.contentVisibility() != ContentVisibility::Hidden)
style.setSkippedContentReason(style.contentVisibility());

adjustForSiteSpecificQuirks(style);
}
Expand Down

0 comments on commit 682cdce

Please sign in to comment.