📄 render_layer.cpp
字号:
// overflow:scroll should just enable/disable.
if (m_object->style()->overflow() == OSCROLL) {
m_hBar->setEnabled(needHorizontalBar);
m_vBar->setEnabled(needVerticalBar);
}
// overflow:auto may need to lay out again if scrollbars got added/removed.
bool scrollbarsChanged = (m_object->hasAutoScrollbars()) &&
(haveHorizontalBar != needHorizontalBar || haveVerticalBar != needVerticalBar);
if (scrollbarsChanged) {
setHasHorizontalScrollbar(needHorizontalBar);
setHasVerticalScrollbar(needVerticalBar);
#if APPLE_CHANGES
// Force an update since we know the scrollbars have changed things.
if (m_object->document()->hasDashboardRegions())
m_object->document()->setDashboardRegionsDirty(true);
#endif
m_object->repaint();
if (m_object->style()->overflow() == OAUTO) {
// Our proprietary overflow: overlay value doesn't trigger a layout.
m_object->setNeedsLayout(true);
if (m_object->isRenderBlock())
static_cast<RenderBlock*>(m_object)->layoutBlock(true);
else
m_object->layout();
}
}
// Set up the range (and page step/line step).
if (m_hBar) {
int clientWidth = m_object->clientWidth();
int pageStep = (clientWidth-PAGE_KEEP);
if (pageStep < 0) pageStep = clientWidth;
m_hBar->setSteps(LINE_STEP, pageStep);
#ifdef APPLE_CHANGES
m_hBar->setKnobProportion(clientWidth, m_scrollWidth);
#else
m_hBar->setRange(0, m_scrollWidth-clientWidth);
m_object->repaintRectangle(QRect(m_object->borderLeft(), m_object->borderTop() + clientHeight(),
horizontalScrollbarHeight(),
m_object->width() - m_object->borderLeft() - m_object->borderRight()));
#endif
}
if (m_vBar) {
int clientHeight = m_object->clientHeight();
int pageStep = (clientHeight-PAGE_KEEP);
if (pageStep < 0) pageStep = clientHeight;
m_vBar->setSteps(LINE_STEP, pageStep);
#ifdef APPLE_CHANGES
m_vBar->setKnobProportion(clientHeight, m_scrollHeight);
#else
m_vBar->setRange(0, m_scrollHeight-clientHeight);
#endif
m_object->repaintRectangle(QRect(m_object->borderLeft() + m_object->clientWidth(),
m_object->borderTop(), verticalScrollbarWidth(),
m_object->height() - m_object->borderTop() - m_object->borderBottom()));
}
#if APPLE_CHANGES
// Force an update since we know the scrollbars have changed things.
if (m_object->document()->hasDashboardRegions())
m_object->document()->setDashboardRegionsDirty(true);
#endif
m_object->repaint();
}
#if APPLE_CHANGES
void
RenderLayer::paintScrollbars(QPainter* p, const QRect& damageRect)
{
// Move the widgets if necessary. We normally move and resize widgets during layout, but sometimes
// widgets can move without layout occurring (most notably when you scroll a document that
// contains fixed positioned elements).
if (m_hBar || m_vBar) {
int x = 0;
int y = 0;
convertToLayerCoords(root(), x, y);
QRect layerBounds = QRect(x, y, width(), height());
positionScrollbars(layerBounds);
}
// Now that we're sure the scrollbars are in the right place, paint them.
if (m_hBar)
m_hBar->paint(p, damageRect);
if (m_vBar)
m_vBar->paint(p, damageRect);
}
#endif
bool RenderLayer::scroll(KWQScrollDirection direction, KWQScrollGranularity granularity, float multiplier)
{
bool didHorizontalScroll = false;
bool didVerticalScroll = false;
if (m_hBar != 0) {
if (granularity == KWQScrollDocument) {
// Special-case for the KWQScrollDocument granularity. A document scroll can only be up
// or down and in both cases the horizontal bar goes all the way to the left.
didHorizontalScroll = m_hBar->scroll(KWQScrollLeft, KWQScrollDocument, multiplier);
} else {
didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
}
}
if (m_vBar != 0) {
didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
}
return (didHorizontalScroll || didVerticalScroll);
}
void
RenderLayer::paint(QPainter *p, const QRect& damageRect, bool selectionOnly, RenderObject *paintingRoot)
{
paintLayer(this, p, damageRect, false, selectionOnly, paintingRoot);
}
static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
{
if (paintDirtyRect == clipRect)
return;
p->save();
#if APPLE_CHANGES
p->addClip(clipRect);
#else
QRect clippedRect = p->xForm(clipRect);
QRegion creg(clippedRect);
QRegion old = p->clipRegion();
if (!old.isNull())
creg = old.intersect(creg);
p->setClipRegion(creg);
#endif
}
static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
{
if (paintDirtyRect == clipRect)
return;
p->restore();
}
#ifdef NOKIA_CHANGES
void RenderLayer::getRenderersInRect(RenderLayer* rootLayer, QPtrList<LayerInfo>* layerInfoList,const QRect& rect,int deltaX,int deltaY, int layerZIndex)
{
// Calculate the top left position for the layer.
int x = 0;
int y = 0;
convertToLayerCoords(rootLayer,x,y);
// Ensure our z-order lists are up-to-date.
updateZOrderLists();
// Now walk the sorted list of children with negative z-indices.
if (m_negZOrderList) {
uint count = m_negZOrderList->count();
for (uint i = 0; i < count; i++) {
RenderLayer* child = m_negZOrderList->at(i);
child->getRenderersInRect(rootLayer,layerInfoList,rect,deltaX,deltaY,layerZIndex + zIndex());
}
}
LayerInfo *layerInfo = new LayerInfo;
QPtrList<BoxInfo> *layerBoxInfoList = new QPtrList<BoxInfo>;
layerBoxInfoList->setAutoDelete(true);
layerInfo->boxInfoList = layerBoxInfoList;
layerInfo->zIndex = layerZIndex + zIndex();
layerInfoList->append(layerInfo);
renderer()->getRenderersInRect(*layerBoxInfoList,deltaX + x - renderer()->xPos(), deltaY + y - renderer()->yPos(),rect);
// Now walk the sorted list of children with positive z-indices.
if (m_posZOrderList) {
uint count = m_posZOrderList->count();
for (uint i = 0; i < count; i++) {
RenderLayer* child = m_posZOrderList->at(i);
child->getRenderersInRect(rootLayer,layerInfoList,rect,deltaX,deltaY,layerZIndex + zIndex());
}
}
}
#endif
void
RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
const QRect& paintDirtyRect, bool haveTransparency, bool selectionOnly,
RenderObject *paintingRoot)
{
// Calculate the clip rects we should use.
QRect layerBounds, damageRect, clipRectToApply;
calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
int x = layerBounds.x();
int y = layerBounds.y();
// Ensure our z-order lists are up-to-date.
updateZOrderLists();
#if APPLE_CHANGES
if (isTransparent())
haveTransparency = true;
#endif
// If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
// is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
// Else, our renderer tree may or may not contain the painting root, so we pass that root along
// so it will be tested against as we decend through the renderers.
RenderObject *paintingRootForRenderer = 0;
if (paintingRoot && !m_object->hasAncestor(paintingRoot)) {
paintingRootForRenderer = paintingRoot;
}
// We want to paint our layer, but only if we intersect the damage rect.
bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
#if APPLE_CHANGES
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
beginTransparencyLayers(p);
#endif
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
setClip(p, paintDirtyRect, damageRect);
// Paint the background.
RenderObject::PaintInfo info(p, damageRect, PaintActionBlockBackground, paintingRootForRenderer);
renderer()->paint(info, x - renderer()->xPos(), y - renderer()->yPos());
#if APPLE_CHANGES
// Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
// z-index. We paint after we painted the background/border, so that the scrollbars will
// sit above the background/border.
paintScrollbars(p, damageRect);
#endif
// Restore the clip.
restoreClip(p, paintDirtyRect, damageRect);
}
// Now walk the sorted list of children with negative z-indices.
if (m_negZOrderList) {
uint count = m_negZOrderList->count();
for (uint i = 0; i < count; i++) {
RenderLayer* child = m_negZOrderList->at(i);
child->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, selectionOnly, paintingRoot);
}
}
// Now establish the appropriate clip and paint our child RenderObjects.
if (shouldPaint && !clipRectToApply.isEmpty()) {
#if APPLE_CHANGES
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
beginTransparencyLayers(p);
#endif
// Set up the clip used when painting our children.
setClip(p, paintDirtyRect, clipRectToApply);
int tx = x - renderer()->xPos();
int ty = y - renderer()->yPos();
RenderObject::PaintInfo info(p, clipRectToApply,
selectionOnly ? PaintActionSelection : PaintActionChildBlockBackgrounds,
paintingRootForRenderer);
renderer()->paint(info, tx, ty);
if (!selectionOnly) {
info.phase = PaintActionFloat;
renderer()->paint(info, tx, ty);
info.phase = PaintActionForeground;
renderer()->paint(info, tx, ty);
info.phase = PaintActionOutline;
renderer()->paint(info, tx, ty);
}
// Now restore our clip.
restoreClip(p, paintDirtyRect, clipRectToApply);
}
// Now walk the sorted list of children with positive z-indices.
if (m_posZOrderList) {
uint count = m_posZOrderList->count();
for (uint i = 0; i < count; i++) {
RenderLayer* child = m_posZOrderList->at(i);
child->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, selectionOnly, paintingRoot);
}
}
#if APPLE_CHANGES
// End our transparency layer
if (isTransparent() && m_usedTransparency) {
p->endTransparencyLayer();
m_usedTransparency = false;
}
#endif
}
bool
RenderLayer::hitTest(RenderObject::NodeInfo& info, int x, int y)
{
#if APPLE_CHANGES
// Clear our our scrollbar variable
RenderLayer::gScrollBar = 0;
#endif
QRect damageRect(m_x, m_y, width(), height());
RenderLayer* insideLayer = hitTestLayer(this, info, x, y, damageRect);
// Now determine if the result is inside an anchor; make sure an image map wins if
// it already set URLElement and only use the innermost.
DOM::NodeImpl* node = info.innerNode();
while (node) {
if (node->hasAnchor() && !info.URLElement())
info.setURLElement(node);
node = node->parentNode();
}
// Next set up the correct :hover/:active state along the new chain.
updateHoverActiveState(info);
// Now return whether we were inside this layer (this will always be true for the root
// layer).
return insideLayer;
}
RenderLayer*
RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
int xMousePos, int yMousePos, const QRect& hitTestRect)
{
// Calculate the clip rects we should use.
QRect layerBounds, bgRect, fgRect;
calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
// Ensure our z-order lists are up-to-date.
updateZOrderLists();
// This variable tracks which layer the mouse ends up being inside. The minute we find an insideLayer,
// we are done and can return it.
RenderLayer* insideLayer = 0;
// Begin by walking our list of positive layers from highest z-index down to the lowest
// z-index.
if (m_posZOrderList) {
uint count = m_posZOrderList->count();
for (int i = count-1; i >= 0; i--) {
RenderLayer* child = m_posZOrderList->at(i);
insideLayer = child->hitTestLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
if (insideLayer)
return insideLayer;
}
}
// Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
if (containsPoint(xMousePos, yMousePos, fgRect) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -