Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
<textarea> with float:left disappears when editing text
https://bugs.webkit.org/show_bug.cgi?id=132188
<rdar://problem/110093535>

Reviewed by Simon Fraser.

Consider the following example:
 <div id=top>
   <div id=middle>
     <div id=float_box style="width: 100px; height: 100px;"></div>
   </div>
 </div>
1. A float box can intrude into multiple containers ("top" and "middle").
2. Containers construct FloatingObjects for intruding floats (multiple FloatingObjects can point to the same float when it crosses containers).
3. Float boxes (usually) are painted by the top most container where they intrude ("top").
4. However self-painting float boxes always paint themselves (this is not specific to floats, all renderers behave like this).
5. FloatingObject's m_paintsFloat controls which container is responsible for painting the (non-self-painting) float box.

When a float box goes from self-painting to non-self painting, we need to ensure that one of its containers takes care of painting it
by adjusting the associated FloatingObject's paint flag.
It is usually done as part of the layout process at RenderBlockFlow::addIntrudingFloats when containers finish running layout
on their child renderers (including float boxes) (i.e. the containing block chain takes care of updating this bit).

However when the float box is the root of the layout (i.e. subtree layout) none of its containers get the chance to update this paint flag since
layout flow never reaches said ancestors. (note when the layout's entry point is the float box, it's guaranteed that
none of the intruding/overhanging properties change at the containing block level (i.e. no need to extend the layout to the ancestor chain).
At this point this is really only about ensuring that one of the ancestors (through the already constructed FloatingObjects) starts painting this float box.

* Source/WebCore/rendering/RenderBox.cpp:
(WebCore::RenderBox::updateFloatBoxAfterSelfPaintingLayerChange):
* Source/WebCore/rendering/RenderBox.h:
* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::calculateClipRects const):

Canonical link: https://commits.webkit.org/264943@main
  • Loading branch information
alanbaradlay committed Jun 7, 2023
1 parent 7584d30 commit df850bb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
42 changes: 42 additions & 0 deletions Source/WebCore/rendering/RenderBox.cpp
Expand Up @@ -5720,4 +5720,46 @@ bool RenderBox::requiresLayer() const
|| style().containsLayout() || !style().hasAutoUsedZIndex() || hasRunningAcceleratedAnimations();
}

void RenderBox::updateFloatPainterAfterSelfPaintingLayerChange()
{
ASSERT(isFloating());
ASSERT(!hasLayer() || !layer()->isSelfPaintingLayer());

// Find the ancestor renderer that is supposed to paint this float now that it is not self painting anymore.
auto floatingObjectForFloatPainting = [&]() -> FloatingObject* {
auto& layoutContext = view().frameView().layoutContext();
if (!layoutContext.isInLayout() || layoutContext.subtreeLayoutRoot() != this)
return nullptr;

FloatingObject* floatPainter = nullptr;
for (auto* ancestor = containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {
auto* blockFlow = dynamicDowncast<RenderBlockFlow>(*ancestor);
if (!blockFlow) {
ASSERT_NOT_REACHED();
break;
}
auto* floatingObjects = blockFlow->floatingObjectSet();
if (!floatingObjects)
break;
auto blockFlowContainsThisFloat = false;
for (auto& floatingObject : *floatingObjects) {
blockFlowContainsThisFloat = &floatingObject->renderer() == this;
if (blockFlowContainsThisFloat) {
floatPainter = floatingObject.get();
if (blockFlow->hasLayer() && blockFlow->layer()->isSelfPaintingLayer())
return floatPainter;
break;
}
}
if (!blockFlowContainsThisFloat)
break;
}
// There has to be an ancestor with a floating object assigned to this renderer.
ASSERT(floatPainter);
return floatPainter;
};
if (auto* floatingObject = floatingObjectForFloatPainting())
floatingObject->setPaintsFloat(true);
}

} // namespace WebCore
2 changes: 2 additions & 0 deletions Source/WebCore/rendering/RenderBox.h
Expand Up @@ -653,6 +653,8 @@ class RenderBox : public RenderBoxModelObject {
bool establishesIndependentFormattingContext() const override;
bool establishesBlockFormattingContext() const;

void updateFloatPainterAfterSelfPaintingLayerChange();

protected:
RenderBox(Element&, RenderStyle&&, BaseTypeFlags);
RenderBox(Document&, RenderStyle&&, BaseTypeFlags);
Expand Down
7 changes: 7 additions & 0 deletions Source/WebCore/rendering/RenderLayer.cpp
Expand Up @@ -5258,6 +5258,13 @@ void RenderLayer::updateSelfPaintingLayer()
else {
parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
clearRepaintRects();
auto updateFloatBoxShouldPaintIfApplicable = [&] {
auto* renderBox = this->renderBox();
if (!renderBox || !renderBox->isFloating())
return;
renderBox->updateFloatPainterAfterSelfPaintingLayerChange();
};
updateFloatBoxShouldPaintIfApplicable();
}
}

Expand Down

0 comments on commit df850bb

Please sign in to comment.