WebKitNamedFlow.cpp [plain text]
#include "config.h"
#include "WebKitNamedFlow.h"
#include "EventNames.h"
#include "NamedFlowCollection.h"
#include "NoEventDispatchAssertion.h"
#include "RenderNamedFlowFragment.h"
#include "RenderNamedFlowThread.h"
#include "RenderRegion.h"
#include "StaticNodeList.h"
#include "UIEvent.h"
namespace WebCore {
WebKitNamedFlow::WebKitNamedFlow(NamedFlowCollection& manager, const AtomicString& flowThreadName)
: m_flowThreadName(flowThreadName)
, m_flowManager(&manager)
, m_parentFlowThread(nullptr)
{
}
WebKitNamedFlow::~WebKitNamedFlow()
{
m_flowManager->discardNamedFlow(this);
}
Ref<WebKitNamedFlow> WebKitNamedFlow::create(NamedFlowCollection& manager, const AtomicString& flowThreadName)
{
return adoptRef(*new WebKitNamedFlow(manager, flowThreadName));
}
const AtomicString& WebKitNamedFlow::name() const
{
return m_flowThreadName;
}
bool WebKitNamedFlow::overset() const
{
if (m_flowManager->document())
m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
if (!m_parentFlowThread || !m_parentFlowThread->hasRegions())
return true;
const auto& namedFlowFragment = downcast<RenderNamedFlowFragment>(*m_parentFlowThread->lastRegion());
return namedFlowFragment.regionOversetState() == RegionOverset;
}
static inline bool inFlowThread(RenderObject* renderer, RenderNamedFlowThread* flowThread)
{
if (!renderer)
return false;
RenderFlowThread* currentFlowThread = renderer->flowThreadContainingBlock();
if (flowThread == currentFlowThread)
return true;
if (renderer->flowThreadState() != RenderObject::InsideInFlowThread)
return false;
return inFlowThread(currentFlowThread->containingBlock(), flowThread);
}
int WebKitNamedFlow::firstEmptyRegionIndex() const
{
if (m_flowManager->document())
m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
if (!m_parentFlowThread)
return -1;
const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
if (regionList.isEmpty())
return -1;
int countNonPseudoRegions = -1;
for (const auto& renderRegion : regionList) {
const auto& namedFlowFragment = downcast<RenderNamedFlowFragment>(*renderRegion);
if (namedFlowFragment.isPseudoElementRegion())
continue;
++countNonPseudoRegions;
if (namedFlowFragment.regionOversetState() == RegionEmpty)
return countNonPseudoRegions;
}
return -1;
}
Ref<NodeList> WebKitNamedFlow::getRegionsByContent(Node* contentNode)
{
if (!contentNode)
return StaticElementList::create();
if (m_flowManager->document())
m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
if (!m_parentFlowThread)
return StaticElementList::create();
Vector<Ref<Element>> regionElements;
if (inFlowThread(contentNode->renderer(), m_parentFlowThread)) {
const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
for (const auto& renderRegion : regionList) {
const auto& namedFlowFragment = downcast<RenderNamedFlowFragment>(*renderRegion);
if (namedFlowFragment.isPseudoElementRegion())
continue;
if (m_parentFlowThread->objectInFlowRegion(contentNode->renderer(), &namedFlowFragment)) {
ASSERT(namedFlowFragment.generatingElement());
regionElements.append(*namedFlowFragment.generatingElement());
}
}
}
return StaticElementList::create(WTFMove(regionElements));
}
Ref<NodeList> WebKitNamedFlow::getRegions()
{
if (m_flowManager->document())
m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
if (!m_parentFlowThread)
return StaticElementList::create();
Vector<Ref<Element>> regionElements;
const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
for (const auto& renderRegion : regionList) {
const auto& namedFlowFragment = downcast<RenderNamedFlowFragment>(*renderRegion);
if (namedFlowFragment.isPseudoElementRegion())
continue;
ASSERT(namedFlowFragment.generatingElement());
regionElements.append(*namedFlowFragment.generatingElement());
}
return StaticElementList::create(WTFMove(regionElements));
}
Ref<NodeList> WebKitNamedFlow::getContent()
{
if (m_flowManager->document())
m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
if (!m_parentFlowThread)
return StaticElementList::create();
auto& contentElementsList = m_parentFlowThread->contentElements();
Vector<Ref<Element>> contentElements;
contentElements.reserveInitialCapacity(contentElementsList.size());
for (auto& element : contentElementsList) {
ASSERT(element->computedStyle()->flowThread() == m_parentFlowThread->flowThreadName());
contentElements.uncheckedAppend(*element);
}
return StaticElementList::create(WTFMove(contentElements));
}
void WebKitNamedFlow::setRenderer(RenderNamedFlowThread* parentFlowThread)
{
ASSERT((!m_parentFlowThread && parentFlowThread) || (m_parentFlowThread && !parentFlowThread));
m_parentFlowThread = parentFlowThread;
}
void WebKitNamedFlow::dispatchRegionOversetChangeEvent()
{
ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
if (flowState() == FlowStateNull)
return;
dispatchEvent(UIEvent::create(eventNames().webkitregionoversetchangeEvent, false, false, m_flowManager->document()->defaultView(), 0));
}
ScriptExecutionContext* WebKitNamedFlow::scriptExecutionContext() const
{
return m_flowManager->document();
}
Node* WebKitNamedFlow::ownerNode() const
{
return m_flowManager->document();
}
}