📄 render_layer.cpp
字号:
if (beforeChild) {
beforeChild->setPreviousSibling(child);
child->setNextSibling(beforeChild);
}
else
setLastChild(child);
child->setParent(this);
// Dirty the z-order list in which we are contained. The stackingContext() can be null in the
// case where we're building up generated content layers. This is ok, since the lists will start
// off dirty in that case anyway.
RenderLayer* stackingContext = child->stackingContext();
if (stackingContext)
stackingContext->dirtyZOrderLists();
}
RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
{
// remove the child
if (oldChild->previousSibling())
oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
if (oldChild->nextSibling())
oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
if (m_first == oldChild)
m_first = oldChild->nextSibling();
if (m_last == oldChild)
m_last = oldChild->previousSibling();
// Dirty the z-order list in which we are contained. When called via the
// reattachment process in removeOnlyThisLayer, the layer may already be disconnected
// from the main layer tree, so we need to null-check the |stackingContext| value.
RenderLayer* stackingContext = oldChild->stackingContext();
if (stackingContext)
oldChild->stackingContext()->dirtyZOrderLists();
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
oldChild->setParent(0);
return oldChild;
}
void RenderLayer::removeOnlyThisLayer()
{
if (!m_parent)
return;
// Dirty the clip rects.
clearClipRects();
// Remove us from the parent.
RenderLayer* parent = m_parent;
RenderLayer* nextSib = nextSibling();
parent->removeChild(this);
// Now walk our kids and reattach them to our parent.
RenderLayer* current = m_first;
while (current) {
RenderLayer* next = current->nextSibling();
removeChild(current);
parent->addChild(current, nextSib);
current = next;
}
detach(renderer()->renderArena());
}
void RenderLayer::insertOnlyThisLayer()
{
if (!m_parent && renderer()->parent()) {
// We need to connect ourselves when our renderer() has a parent.
// Find our enclosingLayer and add ourselves.
RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
if (parentLayer)
parentLayer->addChild(this,
renderer()->parent()->findNextLayer(parentLayer, renderer()));
}
// Remove all descendant layers from the hierarchy and add them to the new position.
for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
curr->moveLayers(m_parent, this);
// Clear out all the clip rects.
clearClipRects();
}
void
RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
{
if (ancestorLayer == this)
return;
if (m_object->style()->position() == FIXED) {
// Add in the offset of the view. We can obtain this by calling
// absolutePosition() on the RenderCanvas.
int xOff, yOff;
m_object->absolutePosition(xOff, yOff, true);
x += xOff;
y += yOff;
return;
}
RenderLayer* parentLayer;
if (m_object->style()->position() == ABSOLUTE)
parentLayer = enclosingPositionedAncestor();
else
parentLayer = parent();
if (!parentLayer) return;
parentLayer->convertToLayerCoords(ancestorLayer, x, y);
x += xPos();
y += yPos();
}
void
RenderLayer::scrollOffset(int& x, int& y)
{
x += scrollXOffset();
y += scrollYOffset();
}
void
RenderLayer::subtractScrollOffset(int& x, int& y)
{
x -= scrollXOffset();
y -= scrollYOffset();
}
void
RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
{
if (renderer()->style()->overflow() != OMARQUEE) {
if (x < 0) x = 0;
if (y < 0) y = 0;
// Call the scrollWidth/Height functions so that the dimensions will be computed if they need
// to be (for overflow:hidden blocks).
int maxX = scrollWidth() - m_object->clientWidth();
int maxY = scrollHeight() - m_object->clientHeight();
if (x > maxX) x = maxX;
if (y > maxY) y = maxY;
}
// FIXME: Eventually, we will want to perform a blit. For now never
// blit, since the check for blitting is going to be very
// complicated (since it will involve testing whether our layer
// is either occluded by another layer or clipped by an enclosing
// layer or contains fixed backgrounds, etc.).
m_scrollX = x;
m_scrollY = y;
// Update the positions of our child layers.
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->updateLayerPositions(false, false);
#if APPLE_CHANGES
// Move our widgets.
m_object->updateWidgetPositions();
// Update dashboard regions, scrolling may change the clip of a
// particular region.
RenderCanvas *canvas = renderer()->canvas();
if (canvas)
canvas->view()->updateDashboardRegions();
#endif
// Fire the scroll DOM event.
m_object->element()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
// Just schedule a full repaint of our object.
if (repaint)
m_object->repaint();
if (updateScrollbars) {
if (m_hBar)
m_hBar->setValue(m_scrollX);
if (m_vBar)
m_vBar->setValue(m_scrollY);
}
}
void
RenderLayer::updateScrollPositionFromScrollbars()
{
bool needUpdate = false;
int newX = m_scrollX;
int newY = m_scrollY;
if (m_hBar) {
newX = m_hBar->value();
if (newX != m_scrollX)
needUpdate = true;
}
if (m_vBar) {
newY = m_vBar->value();
if (newY != m_scrollY)
needUpdate = true;
}
if (needUpdate)
scrollToOffset(newX, newY, false);
}
void
RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
{
if (hasScrollbar && !m_hBar) {
QScrollView* scrollView = m_object->element()->getDocument()->view();
m_hBar = new QScrollBar(Qt::Horizontal, 0);
scrollView->addChild(m_hBar, 0, -50000);
if (!m_scrollMediator)
m_scrollMediator = new RenderScrollMediator(this);
m_scrollMediator->connect(m_hBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)));
}
else if (!hasScrollbar && m_hBar) {
QScrollView* scrollView = m_object->element()->getDocument()->view();
scrollView->removeChild (m_hBar);
m_scrollMediator->disconnect(m_hBar, SIGNAL(valueChanged(int)),
m_scrollMediator, SLOT(slotValueChanged(int)));
delete m_hBar;
m_hBar = 0;
}
}
void
RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
{
if (hasScrollbar && !m_vBar) {
QScrollView* scrollView = m_object->element()->getDocument()->view();
m_vBar = new QScrollBar(Qt::Vertical, 0);
scrollView->addChild(m_vBar, 0, -50000);
if (!m_scrollMediator)
m_scrollMediator = new RenderScrollMediator(this);
m_scrollMediator->connect(m_vBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)));
}
else if (!hasScrollbar && m_vBar) {
QScrollView* scrollView = m_object->element()->getDocument()->view();
scrollView->removeChild (m_vBar);
m_scrollMediator->disconnect(m_vBar, SIGNAL(valueChanged(int)),
m_scrollMediator, SLOT(slotValueChanged(int)));
delete m_vBar;
m_vBar = 0;
}
}
int
RenderLayer::verticalScrollbarWidth()
{
if (!m_vBar)
return 0;
return m_vBar->width();
}
int
RenderLayer::horizontalScrollbarHeight()
{
if (!m_hBar)
return 0;
return m_hBar->height();
}
void
RenderLayer::moveScrollbarsAside()
{
if (m_hBar)
m_hBar->move(0, -50000);
if (m_vBar)
m_vBar->move(0, -50000);
}
void
RenderLayer::positionScrollbars(const QRect& absBounds)
{
if (m_vBar) {
m_vBar->move(absBounds.x()+absBounds.width()-m_object->borderRight()-m_vBar->width(),
absBounds.y()+m_object->borderTop());
m_vBar->resize(m_vBar->width(), absBounds.height() -
(m_object->borderTop()+m_object->borderBottom()) -
(m_hBar ? m_hBar->height()-1 : 0));
}
if (m_hBar) {
m_hBar->move(absBounds.x()+m_object->borderLeft(),
absBounds.y()+absBounds.height()-m_object->borderBottom()-m_hBar->height());
m_hBar->resize(absBounds.width() - (m_object->borderLeft()+m_object->borderRight()) -
(m_vBar ? m_vBar->width()-1 : 0),
m_hBar->height());
}
}
#define LINE_STEP 10
#define PAGE_KEEP 40
int RenderLayer::scrollWidth()
{
if (m_scrollDimensionsDirty)
computeScrollDimensions();
return m_scrollWidth;
}
int RenderLayer::scrollHeight()
{
if (m_scrollDimensionsDirty)
computeScrollDimensions();
return m_scrollHeight;
}
void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
{
m_scrollDimensionsDirty = false;
int rightPos = m_object->rightmostPosition(true, false) - m_object->borderLeft();
int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
int clientWidth = m_object->clientWidth();
int clientHeight = m_object->clientHeight();
m_scrollWidth = kMax(rightPos, clientWidth);
m_scrollHeight = kMax(bottomPos, clientHeight);
if (needHBar)
*needHBar = rightPos > clientWidth;
if (needVBar)
*needVBar = bottomPos > clientHeight;
}
void
RenderLayer::updateScrollInfoAfterLayout()
{
m_scrollDimensionsDirty = true;
if (m_object->style()->overflow() == OHIDDEN)
return; // All we had to do was dirty.
bool needHorizontalBar, needVerticalBar;
computeScrollDimensions(&needHorizontalBar, &needVerticalBar);
if (m_object->style()->overflow() != OMARQUEE) {
// Layout may cause us to be in an invalid scroll position. In this case we need
// to pull our scroll offsets back to the max (or push them up to the min).
int newX = kMax(0, kMin(m_scrollX, scrollWidth() - m_object->clientWidth()));
int newY = kMax(0, kMin(m_scrollY, scrollHeight() - m_object->clientHeight()));
if (newX != m_scrollX || newY != m_scrollY)
scrollToOffset(newX, newY);
}
bool haveHorizontalBar = m_hBar;
bool haveVerticalBar = m_vBar;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -