예제 #1
0
int RenderTheme::baselinePosition(const RenderBox& box) const
{
#if USE(NEW_THEME)
    return box.height() + box.marginTop() + m_theme->baselinePositionAdjustment(box.style().appearance()) * box.style().effectiveZoom();
#else
    return box.height() + box.marginTop();
#endif
}
예제 #2
0
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(*this))
        return;

    LayoutRect paintRect(paintOffset, size());
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlockFlow::paintBoxDecorations(paintInfo, paintOffset);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style().isHorizontalWritingMode()) {
        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
        paintRect.setHeight(paintRect.height() - yOff);
        paintRect.setY(paintRect.y() + yOff);
    } else {
        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
        paintRect.setWidth(paintRect.width() - xOff);
        paintRect.setX(paintRect.x() + xOff);
    }

    if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
        paintBoxShadow(paintInfo, paintRect, style(), Normal);
    paintFillLayers(paintInfo, style().visitedDependentColor(CSSPropertyBackgroundColor), style().backgroundLayers(), paintRect);
    paintBoxShadow(paintInfo, paintRect, style(), Inset);

    if (!style().hasBorder())
        return;
    
    // Create a clipping region around the legend and paint the border as normal
    GraphicsContext* graphicsContext = paintInfo.context;
    GraphicsContextStateSaver stateSaver(*graphicsContext);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    LayoutRect clipRect;
    if (style().isHorizontalWritingMode()) {
        clipRect.setX(paintRect.x() + legend->x());
        clipRect.setY(paintRect.y());
        clipRect.setWidth(legend->width());
        clipRect.setHeight(std::max<LayoutUnit>(style().borderTopWidth(), legend->height() - ((legend->height() - borderTop()) / 2)));
    } else {
        clipRect.setX(paintRect.x());
        clipRect.setY(paintRect.y() + legend->y());
        clipRect.setWidth(std::max<LayoutUnit>(style().borderLeftWidth(), legend->width()));
        clipRect.setHeight(legend->height());
    }
    graphicsContext->clipOut(snapRectToDevicePixels(clipRect, document().deviceScaleFactor()));

    paintBorder(paintInfo, paintRect, style());
}
void RenderTextControlSingleLine::layout()
{
    int oldHeight = height();
    calcHeight();

    int oldWidth = width();
    calcWidth();

    bool relayoutChildren = oldHeight != height() || oldWidth != width();

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0;

    // Set the text block height
    int desiredHeight = textBlockHeight();
    int currentHeight = innerTextRenderer->height();

    if (m_innerBlock || currentHeight > height()) {
        if (desiredHeight != currentHeight)
            relayoutChildren = true;
        innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
    }

    if (m_innerBlock) {
        ASSERT(innerBlockRenderer);
        if (desiredHeight != innerBlockRenderer->height())
            relayoutChildren = true;
        innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
    }

    // Set the text block width
    int desiredWidth = textBlockWidth();
    if (desiredWidth != innerTextRenderer->width())
        relayoutChildren = true;
    innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));

    if (m_innerBlock) {
        int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight();
        if (innerBlockWidth != innerBlockRenderer->width())
            relayoutChildren = true;
        innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));
    }

    RenderBlock::layoutBlock(relayoutChildren);

    // For text fields, center the inner text vertically
    // Don't do this for search fields, since we don't honor height for them
    if (!m_innerBlock) {
        currentHeight = innerTextRenderer->height();
        if (currentHeight < height())
            innerTextRenderer->setLocation(innerTextRenderer->x(), (height() - currentHeight) / 2);
    }
}
예제 #4
0
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
        h -= yOff;
        ty += yOff;
    } else {
        int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
        w -= xOff;
        tx += xOff;
    }

    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);

    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h);
    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);

    if (!style()->hasBorder())
        return;
    
    // Create a clipping region around the legend and paint the border as normal
    GraphicsContext* graphicsContext = paintInfo.context;
    graphicsContext->save();

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int clipTop = ty;
        int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());
        graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop, legend->width(), clipHeight));
    } else {
        int clipLeft = tx;
        int clipWidth = max(static_cast<int>(style()->borderLeftWidth()), legend->width());
        graphicsContext->clipOut(IntRect(clipLeft, ty + legend->y(), clipWidth, legend->height()));
    }

    paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);

    graphicsContext->restore();
}
예제 #5
0
void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutRect paintRect = LayoutRect(paintOffset, size());
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlockFlow::paintMask(paintInfo, paintOffset);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style().isHorizontalWritingMode()) {
        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
        paintRect.expand(0, -yOff);
        paintRect.move(0, yOff);
    } else {
        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
        paintRect.expand(-xOff, 0);
        paintRect.move(xOff, 0);
    }

    paintMaskImages(paintInfo, paintRect);
}
예제 #6
0
void RenderSliderContainer::layout()
{
    HTMLInputElement* input = node()->shadowAncestorNode()->toInputElement();
    bool isVertical = hasVerticalAppearance(input);
    style()->setBoxOrient(isVertical ? VERTICAL : HORIZONTAL);
    // Sets the concrete height if the height of the <input> is not fixed or a
    // percentage value because a percentage height value of this box won't be
    // based on the <input> height in such case.
    Length inputHeight = input->renderer()->style()->height();
    RenderObject* trackRenderer = node()->firstChild()->renderer();
    if (!isVertical && input->renderer()->isSlider() && !inputHeight.isFixed() && !inputHeight.isPercent()) {
        RenderObject* thumbRenderer = input->shadowTree()->oldestShadowRoot()->firstChild()->firstChild()->firstChild()->renderer();
        if (thumbRenderer) {
            style()->setHeight(thumbRenderer->style()->height());
            if (trackRenderer)
                trackRenderer->style()->setHeight(thumbRenderer->style()->height());
        }
    } else {
        style()->setHeight(Length(100, Percent));
        if (trackRenderer)
            trackRenderer->style()->setHeight(Length());
    }

    RenderDeprecatedFlexibleBox::layout();

    // Percentage 'top' for the thumb doesn't work if the parent style has no
    // concrete height.
    Node* track = node()->firstChild();
    if (track && track->renderer()->isBox()) {
        RenderBox* trackBox = track->renderBox();
        trackBox->style()->setHeight(Length(trackBox->height() - trackBox->borderAndPaddingHeight(), Fixed));
    }
}
예제 #7
0
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
{
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintMask(paintInfo, tx, ty);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
        h -= yOff;
        ty += yOff;
    } else {
        int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
        w -= xOff;
        tx += xOff;
    }

    paintMaskImages(paintInfo, tx, ty, w, h);
}
예제 #8
0
void SpinButtonElement::defaultEventHandler(Event* event)
{
    if (!event->isMouseEvent()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    RenderBox* box = renderBox();
    if (!box) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowAncestorNode()));
    if (input->disabled() || input->isReadOnlyFormControl()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
    IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
    if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
        if (box->borderBoxRect().contains(local)) {
            // The following functions of HTMLInputElement may run JavaScript
            // code which detaches this shadow node. We need to take a reference
            // and check renderer() after such function calls.
            RefPtr<Node> protector(this);
            input->focus();
            input->select();
            if (renderer()) {
                input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1);
                if (renderer())
                    startRepeatingTimer();
            }
            event->setDefaultHandled();
        }
    } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton)
        stopRepeatingTimer();
    else if (event->type() == eventNames().mousemoveEvent) {
        if (box->borderBoxRect().contains(local)) {
            if (!m_capturing) {
                if (Frame* frame = document()->frame()) {
                    frame->eventHandler()->setCapturingMouseEventsNode(this);
                    m_capturing = true;
                }
            }
            UpDownState oldUpDownState = m_upDownState;
            m_upDownState = local.y() < box->height() / 2 ? Up : Down;
            if (m_upDownState != oldUpDownState)
                renderer()->repaint();
        } else
            releaseCapture();
    }

    if (!event->defaultHandled())
        HTMLDivElement::defaultEventHandler(event);
}
예제 #9
0
LayoutPoint RenderTheme::volumeSliderOffsetFromMuteButton(const RenderBox& muteButtonBox, const LayoutSize& size) const
{
    LayoutUnit y = -size.height();
    FloatPoint absPoint = muteButtonBox.localToAbsolute(FloatPoint(muteButtonBox.offsetLeft(), y), IsFixed | UseTransforms);
    if (absPoint.y() < 0)
        y = muteButtonBox.height();
    return LayoutPoint(0, y);
}
void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, HTMLElement& scrollingElement, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle)
{
    if (scrollingElementStyle.scrollSnapType() == ScrollSnapType::None) {
        scrollableArea.clearHorizontalSnapOffsets();
        scrollableArea.clearVerticalSnapOffsets();
        return;
    }

    LayoutUnit viewWidth = scrollingElementBox.width();
    LayoutUnit viewHeight = scrollingElementBox.height();
    LayoutUnit scrollWidth = scrollingElementBox.scrollWidth();
    LayoutUnit scrollHeight = scrollingElementBox.scrollHeight();
    bool canComputeHorizontalOffsets = scrollWidth > 0 && viewWidth > 0 && viewWidth < scrollWidth;
    bool canComputeVerticalOffsets = scrollHeight > 0 && viewHeight > 0 && viewHeight < scrollHeight;

    if (!canComputeHorizontalOffsets)
        scrollableArea.clearHorizontalSnapOffsets();
    if (!canComputeVerticalOffsets)
        scrollableArea.clearVerticalSnapOffsets();

    if (!canComputeHorizontalOffsets && !canComputeVerticalOffsets)
        return;

    Vector<LayoutUnit> horizontalSnapOffsetSubsequence;
    Vector<LayoutUnit> verticalSnapOffsetSubsequence;

    bool scrollSnapPointsXUsesElements = styleUsesElements(ScrollEventAxis::Horizontal, scrollingElementStyle);
    bool scrollSnapPointsYUsesElements = styleUsesElements(ScrollEventAxis::Vertical , scrollingElementStyle);

    if (scrollSnapPointsXUsesElements || scrollSnapPointsYUsesElements) {
        bool shouldAddHorizontalChildOffsets = scrollSnapPointsXUsesElements && canComputeHorizontalOffsets;
        bool shouldAddVerticalChildOffsets = scrollSnapPointsYUsesElements && canComputeVerticalOffsets;
        appendChildSnapOffsets(scrollingElement, shouldAddHorizontalChildOffsets, horizontalSnapOffsetSubsequence, shouldAddVerticalChildOffsets, verticalSnapOffsetSubsequence);
    }

    if (scrollingElementStyle.scrollSnapPointsX() && !scrollSnapPointsXUsesElements && canComputeHorizontalOffsets) {
        for (auto& snapLength : scrollingElementStyle.scrollSnapPointsX()->offsets)
            horizontalSnapOffsetSubsequence.append(valueForLength(snapLength, viewWidth));
    }

    if (scrollingElementStyle.scrollSnapPointsY() && !scrollSnapPointsYUsesElements && canComputeVerticalOffsets) {
        for (auto& snapLength : scrollingElementStyle.scrollSnapPointsY()->offsets)
            verticalSnapOffsetSubsequence.append(valueForLength(snapLength, viewHeight));
    }

    if (canComputeHorizontalOffsets) {
        auto horizontalSnapOffsets = std::make_unique<Vector<LayoutUnit>>();
        updateFromStyle(*horizontalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Horizontal, viewWidth, scrollWidth, horizontalSnapOffsetSubsequence);
        scrollableArea.setHorizontalSnapOffsets(WTF::move(horizontalSnapOffsets));
    }
    if (canComputeVerticalOffsets) {
        auto verticalSnapOffsets = std::make_unique<Vector<LayoutUnit>>();
        updateFromStyle(*verticalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Vertical, viewHeight, scrollHeight, verticalSnapOffsetSubsequence);
        scrollableArea.setVerticalSnapOffsets(WTF::move(verticalSnapOffsets));
    }
}
예제 #11
0
void RenderSliderContainer::layout()
{
    ASSERT(element()->shadowHost());
    auto& input = downcast<HTMLInputElement>(*element()->shadowHost());
    bool isVertical = hasVerticalAppearance(input);
    mutableStyle().setFlexDirection(isVertical ? FlowColumn : FlowRow);
    TextDirection oldTextDirection = style().direction();
    if (isVertical) {
        // FIXME: Work around rounding issues in RTL vertical sliders. We want them to
        // render identically to LTR vertical sliders. We can remove this work around when
        // subpixel rendering is enabled on all ports.
        mutableStyle().setDirection(LTR);
    }

    RenderBox* thumb = input.sliderThumbElement() ? input.sliderThumbElement()->renderBox() : nullptr;
    RenderBox* track = input.sliderTrackElement() ? input.sliderTrackElement()->renderBox() : nullptr;
    // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place.
    // FIXME: Make a custom Render class for the track and move the thumb positioning code there.
    if (track)
        track->setChildNeedsLayout(MarkOnlyThis);

    RenderFlexibleBox::layout();

    mutableStyle().setDirection(oldTextDirection);
    // These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector).
    if (!thumb || !track)
        return;

    double percentageOffset = sliderPosition(input).toDouble();
    LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth();
    availableExtent -= isVertical ? thumb->height() : thumb->width();
    LayoutUnit offset = percentageOffset * availableExtent;
    LayoutPoint thumbLocation = thumb->location();
    if (isVertical)
        thumbLocation.setY(thumbLocation.y() + track->contentHeight() - thumb->height() - offset);
    else if (style().isLeftToRightDirection())
        thumbLocation.setX(thumbLocation.x() + offset);
    else
        thumbLocation.setX(thumbLocation.x() - offset);
    thumb->setLocation(thumbLocation);
    thumb->repaint();
}
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);

    int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
    int legendBottom = ty + legend->y() + legend->height();
    h -= yOff;
    ty += yOff;

    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);

    paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
    paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);

    if (!style()->hasBorder())
        return;

    // Save time by not saving and restoring the GraphicsContext in the straight border case
    if (!style()->hasBorderRadius())
        return paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->x(), legend->width(), legendBottom);
    
    // We have rounded borders, create a clipping region 
    // around the legend and paint the border as normal
    GraphicsContext* graphicsContext = paintInfo.context;
    graphicsContext->save();

    int clipTop = ty;
    int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());

    graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop,
                                       legend->width(), clipHeight));
    paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);

    graphicsContext->restore();
}
// Return a set of rectangles that should not be overdrawn by the
// plugin ("cutouts").  This helps implement the "iframe shim"
// technique of overlaying a windowed plugin with content from the
// page.  In a nutshell, iframe elements should occlude plugins when
// they occur higher in the stacking order.
void WebPluginContainerImpl::windowCutOutRects(const IntRect& frameRect,
        Vector<IntRect>& cutOutRects)
{
    RenderObject* pluginNode = m_element->renderer();
    ASSERT(pluginNode);
    if (!pluginNode->style())
        return;
    Vector<const RenderObject*> pluginZstack;
    Vector<const RenderObject*> iframeZstack;
    getObjectStack(pluginNode, &pluginZstack);

    // Get the parent widget
    Widget* parentWidget = this->parent();
    if (!parentWidget->isFrameView())
        return;

    FrameView* parentFrameView = static_cast<FrameView*>(parentWidget);

    const HashSet<RefPtr<Widget> >* children = parentFrameView->children();
    for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != children->end(); ++it) {
        // We only care about FrameView's because iframes show up as FrameViews.
        if (!(*it)->isFrameView())
            continue;

        const FrameView* frameView =
            static_cast<const FrameView*>((*it).get());
        // Check to make sure we can get both the element and the RenderObject
        // for this FrameView, if we can't just move on to the next object.
        if (!frameView->frame() || !frameView->frame()->ownerElement()
                || !frameView->frame()->ownerElement()->renderer())
            continue;

        HTMLElement* element = frameView->frame()->ownerElement();
        RenderObject* iframeRenderer = element->renderer();

        if (element->hasTagName(HTMLNames::iframeTag)
                && iframeRenderer->absoluteBoundingBoxRect().intersects(frameRect)
                && (!iframeRenderer->style() || iframeRenderer->style()->visibility() == VISIBLE)) {
            getObjectStack(iframeRenderer, &iframeZstack);
            if (checkStackOnTop(iframeZstack, pluginZstack)) {
                IntPoint point =
                    roundedIntPoint(iframeRenderer->localToAbsolute());
                RenderBox* rbox = toRenderBox(iframeRenderer);
                IntSize size(rbox->width(), rbox->height());
                cutOutRects.append(IntRect(point, size));
            }
        }
    }
}
예제 #14
0
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(this))
        return;

    LayoutRect paintRect(paintOffset, size());
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintBoxDecorations(paintInfo, paintOffset);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        LayoutUnit yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
        paintRect.setHeight(paintRect.height() - yOff);
        paintRect.setY(paintRect.y() + yOff);
    } else {
        LayoutUnit xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
        paintRect.setWidth(paintRect.width() - xOff);
        paintRect.setX(paintRect.x() + xOff);
    }
    
    paintBoxShadow(paintInfo, paintRect, style(), Normal);
    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect);
    paintBoxShadow(paintInfo, paintRect, style(), Inset);

    if (!style()->hasBorder())
        return;
    
    // Create a clipping region around the legend and paint the border as normal
    GraphicsContext* graphicsContext = paintInfo.context;
    GraphicsContextStateSaver stateSaver(*graphicsContext);

    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
    // cases the legend is embedded in the right and bottom borders respectively.
    // https://bugs.webkit.org/show_bug.cgi?id=47236
    if (style()->isHorizontalWritingMode()) {
        LayoutUnit clipTop = paintRect.y();
        LayoutUnit clipHeight = max(static_cast<LayoutUnit>(style()->borderTopWidth()), legend->height());
        graphicsContext->clipOut(LayoutRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight));
    } else {
        LayoutUnit clipLeft = paintRect.x();
        LayoutUnit clipWidth = max(static_cast<LayoutUnit>(style()->borderLeftWidth()), legend->width());
        graphicsContext->clipOut(LayoutRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height()));
    }

    paintBorder(paintInfo, paintRect, style());
}
예제 #15
0
int RenderView::docHeight() const
{
    int h = lowestPosition();

    // FIXME: This doesn't do any margin collapsing.
    // Instead of this dh computation we should keep the result
    // when we call RenderBlock::layout.
    int dh = 0;
    for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox())
        dh += c->height() + c->marginTop() + c->marginBottom();

    if (dh > h)
        h = dh;

    return h;
}
예제 #16
0
void RenderFrameSet::positionFrames()
{
    RenderBox* child = firstChildBox();
    if (!child)
        return;

    int rows = frameSetElement().totalRows();
    int cols = frameSetElement().totalCols();

    int yPos = 0;
    int borderThickness = frameSetElement().border();
    for (int r = 0; r < rows; r++) {
        int xPos = 0;
        int height = m_rows.m_sizes[r];
        for (int c = 0; c < cols; c++) {
            child->setLocation(IntPoint(xPos, yPos));
            int width = m_cols.m_sizes[c];

            // has to be resized and itself resize its contents
            if (width != child->width() || height != child->height()) {
                child->setWidth(width);
                child->setHeight(height);
#if PLATFORM(IOS)
                // FIXME: Is this iOS-specific?
                child->setNeedsLayout(MarkOnlyThis);
#else
                child->setNeedsLayout();
#endif
                child->layout();
            }

            xPos += width + borderThickness;

            child = child->nextSiblingBox();
            if (!child)
                return;
        }
        yPos += height + borderThickness;
    }

    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
    for (; child; child = child->nextSiblingBox()) {
        child->setWidth(0);
        child->setHeight(0);
        child->clearNeedsLayout();
    }
}
예제 #17
0
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
{
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintMask(paintInfo, tx, ty);

    int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
    h -= yOff;
    ty += yOff;

    paintMaskImages(paintInfo, tx, ty, w, h);
}
예제 #18
0
bool SVGLength::determineViewport(const SVGElement* context, float& width, float& height) const
{
    if (!context)
        return false;

    // Take size from outermost <svg> element.
    Document* document = context->document();
    if (document->documentElement() == context) {
        if (RenderView* view = toRenderView(document->renderer())) {
            width = view->viewWidth();
            height = view->viewHeight();
            return true;
        }

        return false;
    }

    // Resolve value against nearest viewport element (common case: inner <svg> elements)
    SVGElement* viewportElement = context->viewportElement();
    if (viewportElement && viewportElement->isSVG()) {
        const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
        if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
            width = svg->viewBox().width();
            height = svg->viewBox().height();
        } else {
            width = svg->width().value(svg);
            height = svg->height().value(svg);
        }

        return true;
    }
    
    // Resolve value against enclosing non-SVG RenderBox
    if (!context->parentNode() || context->parentNode()->isSVGElement())
        return false;

    RenderObject* renderer = context->renderer();
    if (!renderer || !renderer->isBox())
        return false;

    RenderBox* box = toRenderBox(renderer);
    width = box->width();
    height = box->height();
    return true;
}
예제 #19
0
float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SVGLengthMode mode)
{
    ASSERT(context);

    float width = 0.0f, height = 0.0f;
    SVGElement* viewportElement = context->viewportElement();

    // PercentageOfViewport() is used to resolve all relative-positioned values within a SVG document (fragment)
    Document* doc = context->document();
    if (doc->documentElement() == context) {
        // Resolve value against outermost <svg> element
        if (RenderView* view = toRenderView(doc->renderer())) {
            width = view->viewWidth();
            height = view->viewHeight();
         }
    } else if (viewportElement && viewportElement->isSVG()) {
        // Resolve value against nearest viewport element (common case: inner <svg> elements)
        const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
        if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
            width = svg->viewBox().width();
            height = svg->viewBox().height();
        } else {
            width = svg->width().value(svg);
            height = svg->height().value(svg);
        }
    } else if (context->parent() && !context->parent()->isSVGElement()) {
        // Resolve value against enclosing non-SVG RenderBox
        if (RenderObject* renderer = context->renderer()) {
            if (renderer->isBox()) {
                RenderBox* box = toRenderBox(renderer);
                width = box->width();
                height = box->height();
            }
        }
    }

    if (mode == LengthModeWidth)
        return value * width;
    else if (mode == LengthModeHeight)
        return value * height;
    else if (mode == LengthModeOther)
        return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f);

    return 0.0f;
}
예제 #20
0
float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SVGLengthMode mode)
{
    ASSERT(context);

    float width = 0.0f, height = 0.0f;
    SVGElement* viewportElement = context->viewportElement();

    Document* doc = context->document();
    if (doc->documentElement() == context) {
        // We have to ask the canvas for the full "canvas size"...
        RenderView* view = toRenderView(doc->renderer());
        if (view && view->frameView()) {
            width = view->frameView()->visibleWidth(); // TODO: recheck!
            height = view->frameView()->visibleHeight(); // TODO: recheck!
         }
    } else if (viewportElement && viewportElement->isSVG()) {
        const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
        if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
            width = svg->viewBox().width();
            height = svg->viewBox().height();
        } else {
            width = svg->width().value(svg);
            height = svg->height().value(svg);
        }
    } else if (context->parent() && !context->parent()->isSVGElement()) {
        if (RenderObject* renderer = context->renderer()) {
            if (renderer->isBox()) {
                RenderBox* box = toRenderBox(renderer);
                width = box->width();
                height = box->height();
            }
        }
    }

    if (mode == LengthModeWidth)
        return value * width;
    else if (mode == LengthModeHeight)
        return value * height;
    else if (mode == LengthModeOther)
        return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f);

    return 0.0f;
}
예제 #21
0
void RenderFrameSet::positionFrames()
{
    RenderBox* child = firstChildBox();
    if (!child)
        return;

    int rows = frameSet()->totalRows();
    int cols = frameSet()->totalCols();

    int yPos = 0;
    int borderThickness = frameSet()->border();
    for (int r = 0; r < rows; r++) {
        int xPos = 0;
        int height = m_rows.m_sizes[r];
        for (int c = 0; c < cols; c++) {
            child->setLocation(xPos, yPos);
            int width = m_cols.m_sizes[c];

            // has to be resized and itself resize its contents
            if (width != child->width() || height != child->height()) {
                child->setWidth(width);
                child->setHeight(height);
                child->setNeedsLayout(true);
                child->layout();
            }

            xPos += width + borderThickness;

            child = child->nextSiblingBox();
            if (!child)
                return;
        }
        yPos += height + borderThickness;
    }

    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
    for (; child; child = child->nextSiblingBox()) {
        child->setWidth(0);
        child->setHeight(0);
        child->setNeedsLayout(false);
    }
}
예제 #22
0
void RenderSlider::layout()
{
    // FIXME: Find a way to cascade appearance.
    // http://webkit.org/b/62535
    RenderBox* thumbBox = sliderThumbElementOf(node())->renderBox();
    if (thumbBox && thumbBox->isSliderThumb())
        static_cast<RenderSliderThumb*>(thumbBox)->updateAppearance(style());
    if (RenderObject* limiterRenderer = trackLimiterElementOf(node())->renderer()) {
        if (limiterRenderer->isSliderThumb())
          static_cast<RenderSliderThumb*>(limiterRenderer)->updateAppearance(style());
    }

    RenderBlock::layout();

    if (!thumbBox)
        return;
    LayoutUnit heightDiff = thumbBox->height() - contentHeight();
    if (heightDiff > 0)
        thumbBox->setY(thumbBox->y() - (heightDiff / 2));
}
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    int w = width();
    int h = height();
    RenderBox* legend = findLegend();
    if (!legend)
        return RenderBlock::paintMask(paintInfo, tx, ty);

    int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
    h -= yOff;
    ty += yOff;

    paintMaskImages(paintInfo, tx, ty, w, h);
}
RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
{
    RenderBox* legend = findLegend();
    if (legend) {
        if (relayoutChildren)
            legend->setNeedsLayout(true);
        legend->layoutIfNeeded();

        int xPos;
        if (style()->direction() == RTL) {
            switch (legend->style()->textAlign()) {
                case LEFT:
                    xPos = borderLeft() + paddingLeft();
                    break;
                case CENTER:
                    xPos = (width() - legend->width()) / 2;
                    break;
                default:
                    xPos = width() - paddingRight() - borderRight() - legend->width() - legend->marginRight();
            }
        } else {
            switch (legend->style()->textAlign()) {
                case RIGHT:
                    xPos = width() - paddingRight() - borderRight() - legend->width();
                    break;
                case CENTER:
                    xPos = (width() - legend->width()) / 2;
                    break;
                default:
                    xPos = borderLeft() + paddingLeft() + legend->marginLeft();
            }
        }
        int b = borderTop();
        int h = legend->height();
        legend->setLocation(xPos, max((b-h)/2, 0));
        setHeight(max(b, h) + paddingTop());
    }
    return legend;
}
예제 #25
0
void RenderFrameSet::positionFramesWithFlattening()
{
    RenderBox* child = firstChildBox();
    if (!child)
        return;

    int rows = frameSetElement().totalRows();
    int cols = frameSetElement().totalCols();

    int borderThickness = frameSetElement().border();
    bool repaintNeeded = false;

    // calculate frameset height based on actual content height to eliminate scrolling
    bool out = false;
    for (int r = 0; r < rows && !out; r++) {
        int extra = 0;
        int height = m_rows.m_sizes[r];

        for (int c = 0; c < cols; c++) {
            IntRect oldFrameRect = pixelSnappedIntRect(child->frameRect());

            int width = m_cols.m_sizes[c];

            bool fixedWidth = frameSetElement().colLengths() && frameSetElement().colLengths()[c].isFixed();
            bool fixedHeight = frameSetElement().rowLengths() && frameSetElement().rowLengths()[r].isFixed();

            // has to be resized and itself resize its contents
            if (!fixedWidth)
                child->setWidth(width ? width + extra / (cols - c) : 0);
            else
                child->setWidth(width);
            child->setHeight(height);

            child->setNeedsLayout();

            if (child->isFrameSet())
                toRenderFrameSet(child)->layout();
            else
                toRenderFrame(child)->layoutWithFlattening(fixedWidth, fixedHeight);

            if (child->height() > m_rows.m_sizes[r])
                m_rows.m_sizes[r] = child->height();
            if (child->width() > m_cols.m_sizes[c])
                m_cols.m_sizes[c] = child->width();

            if (child->frameRect() != oldFrameRect)
                repaintNeeded = true;

            // difference between calculated frame width and the width it actually decides to have
            extra += width - m_cols.m_sizes[c];

            child = child->nextSiblingBox();
            if (!child) {
                out = true;
                break;
            }
        }
    }

    int xPos = 0;
    int yPos = 0;
    out = false;
    child = firstChildBox();
    for (int r = 0; r < rows && !out; r++) {
        xPos = 0;
        for (int c = 0; c < cols; c++) {
            // ensure the rows and columns are filled
            IntRect oldRect = pixelSnappedIntRect(child->frameRect());

            child->setLocation(IntPoint(xPos, yPos));
            child->setHeight(m_rows.m_sizes[r]);
            child->setWidth(m_cols.m_sizes[c]);

            if (child->frameRect() != oldRect) {
                repaintNeeded = true;

                // update to final size
                child->setNeedsLayout();
                if (child->isFrameSet())
                    toRenderFrameSet(child)->layout();
                else
                    toRenderFrame(child)->layoutWithFlattening(true, true);
            }

            xPos += m_cols.m_sizes[c] + borderThickness;
            child = child->nextSiblingBox();
            if (!child) {
                out = true;
                break;
            }
        }
        yPos += m_rows.m_sizes[r] + borderThickness;
    }

    setWidth(xPos - borderThickness);
    setHeight(yPos - borderThickness);

    if (repaintNeeded)
        repaint();

    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
    for (; child; child = child->nextSiblingBox()) {
        child->setWidth(0);
        child->setHeight(0);
        child->clearNeedsLayout();
    }
}
void RenderTextControlSingleLine::layout()
{
    SubtreeLayoutScope layoutScope(this);

    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    RenderBox* viewPortRenderer = editingViewPortElement() ? editingViewPortElement()->renderBox() : 0;

    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
    if (innerTextRenderer && !innerTextRenderer->style()->logicalHeight().isAuto()) {
        innerTextRenderer->style()->setLogicalHeight(Length(Auto));
        layoutScope.setNeedsLayout(innerTextRenderer);
    }
    if (viewPortRenderer && !viewPortRenderer->style()->logicalHeight().isAuto()) {
        viewPortRenderer->style()->setLogicalHeight(Length(Auto));
        layoutScope.setNeedsLayout(viewPortRenderer);
    }

    RenderBlockFlow::layoutBlock(false);

    Element* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
    LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
    if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
        if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
            layoutScope.setNeedsLayout(this);

        m_desiredInnerTextLogicalHeight = desiredLogicalHeight;

        innerTextRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
        layoutScope.setNeedsLayout(innerTextRenderer);
        if (viewPortRenderer) {
            viewPortRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
            layoutScope.setNeedsLayout(viewPortRenderer);
        }
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight();
        if (containerLogicalHeight > logicalHeightLimit) {
            containerRenderer->style()->setLogicalHeight(Length(logicalHeightLimit, Fixed));
            layoutScope.setNeedsLayout(this);
        } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) {
            containerRenderer->style()->setLogicalHeight(Length(contentLogicalHeight(), Fixed));
            layoutScope.setNeedsLayout(this);
        } else
            containerRenderer->style()->setLogicalHeight(Length(containerLogicalHeight, Fixed));
    }

    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
    if (needsLayout())
        RenderBlockFlow::layoutBlock(true);

    // Center the child block in the block progression direction (vertical centering for horizontal text fields).
    if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight()) {
        LayoutUnit logicalHeightDiff = innerTextRenderer->logicalHeight() - contentLogicalHeight();
        innerTextRenderer->setLogicalTop(innerTextRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
    } else
        centerContainerIfNeeded(containerRenderer);

    HTMLElement* placeholderElement = inputElement()->placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        LayoutSize innerTextSize;

        if (innerTextRenderer)
            innerTextSize = innerTextRenderer->size();
        placeholderBox->style()->setWidth(Length(innerTextSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed));
        placeholderBox->style()->setHeight(Length(innerTextSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed));
        bool neededLayout = placeholderBox->needsLayout();
        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset;
        if (innerTextRenderer)
            textOffset = innerTextRenderer->location();
        if (editingViewPortElement() && editingViewPortElement()->renderBox())
            textOffset += toLayoutSize(editingViewPortElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);

        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
            // This assumes a shadow tree without floats. If floats are added, the
            // logic should be shared with RenderBlockFlow::layoutBlockChild.
            placeholderBox->repaint();
        }
        // The placeholder gets layout last, after the parent text control and its other children,
        // so in order to get the correct overflow from the placeholder we need to recompute it now.
        if (neededLayout)
            computeOverflow(clientLogicalBottom());
    }
}
예제 #27
0
void RenderTextControlSingleLine::layout()
{
    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    LayoutUnit oldHeight = height();
    computeLogicalHeight();

    LayoutUnit oldWidth = width();
    computeLogicalWidth();

    bool relayoutChildren = oldHeight != height() || oldWidth != width();

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    ASSERT(innerTextRenderer);
    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;
    HTMLElement* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredHeight = textBlockHeight();
    LayoutUnit currentHeight = innerTextRenderer->height();

    LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight();
    if (currentHeight > heightLimit) {
        if (desiredHeight != currentHeight)
            relayoutChildren = true;
        innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
        m_desiredInnerTextHeight = desiredHeight;
        if (innerBlockRenderer)
            innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerHeight = containerRenderer->height();
        if (containerHeight > heightLimit) {
            containerRenderer->style()->setHeight(Length(heightLimit, Fixed));
            relayoutChildren = true;
        } else if (containerRenderer->height() < contentHeight()) {
            containerRenderer->style()->setHeight(Length(contentHeight(), Fixed));
            relayoutChildren = true;
        } else
            containerRenderer->style()->setHeight(Length(containerHeight, Fixed));
    }

    RenderBlock::layoutBlock(relayoutChildren);

    // Center the child block vertically
    currentHeight = innerTextRenderer->height();
    if (!container && currentHeight != contentHeight()) {
        LayoutUnit heightDiff = currentHeight - contentHeight();
        innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
    } else if (inputElement()->isSearchField() && containerRenderer && containerRenderer->height() > contentHeight()) {
        // A quirk for find-in-page box on Safari Windows.
        // http://webkit.org/b/63157
        LayoutUnit heightDiff = containerRenderer->height() - contentHeight();
        containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
    }

    // Ignores the paddings for the inner spin button.
    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
        RenderBox* parentBox = innerSpinBox->parentBox();
        if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
            innerSpinBox->setLocation(LayoutPoint(-paddingLeft(), -paddingTop()));
        else
            innerSpinBox->setLocation(LayoutPoint(parentBox->width() - innerSpinBox->width() + paddingRight(), -paddingTop()));
        innerSpinBox->setHeight(height() - borderTop() - borderBottom());
    }

    HTMLElement* placeholderElement = inputElement()->placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed));
        placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed));
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset = innerTextRenderer->location();
        if (innerBlockElement() && innerBlockElement()->renderBox())
            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);
    }
}
void SpinButtonElement::defaultEventHandler(Event* event)
{
    if (!event->isMouseEvent()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    RenderBox* box = renderBox();
    if (!box) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    if (!shouldRespondToMouseEvents()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    MouseEvent* mouseEvent = toMouseEvent(event);
    IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), UseTransforms));
    if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
        if (box->pixelSnappedBorderBoxRect().contains(local)) {
            // The following functions of HTMLInputElement may run JavaScript
            // code which detaches this shadow node. We need to take a reference
            // and check renderer() after such function calls.
            Ref<SpinButtonElement> protect(*this);
            if (m_spinButtonOwner)
                m_spinButtonOwner->focusAndSelectSpinButtonOwner();
            if (renderer()) {
                if (m_upDownState != Indeterminate) {
                    // A JavaScript event handler called in doStepAction() below
                    // might change the element state and we might need to
                    // cancel the repeating timer by the state change. If we
                    // started the timer after doStepAction(), we would have no
                    // chance to cancel the timer.
                    startRepeatingTimer();
                    doStepAction(m_upDownState == Up ? 1 : -1);
                }
            }
            event->setDefaultHandled();
        }
    } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton)
        stopRepeatingTimer();
    else if (event->type() == eventNames().mousemoveEvent) {
        if (box->pixelSnappedBorderBoxRect().contains(local)) {
            if (!m_capturing) {
                if (Frame* frame = document().frame()) {
                    frame->eventHandler().setCapturingMouseEventsElement(this);
                    m_capturing = true;
                    if (Page* page = document().page())
                        page->chrome().registerPopupOpeningObserver(this);
                }
            }
            UpDownState oldUpDownState = m_upDownState;
            m_upDownState = local.y() < box->height() / 2 ? Up : Down;
            if (m_upDownState != oldUpDownState)
                renderer()->repaint();
        } else {
            releaseCapture();
            m_upDownState = Indeterminate;
        }
    }

    if (!event->defaultHandled())
        HTMLDivElement::defaultEventHandler(event);
}
예제 #29
0
void SpinButtonElement::defaultEventHandler(Event* event)
{
    if (!event->isMouseEvent()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    RenderBox* box = renderBox();
    if (!box) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;        
    }
    
    HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
    if (input->disabled() || input->isReadOnlyFormControl()) {
        if (!event->defaultHandled())
            HTMLDivElement::defaultEventHandler(event);
        return;
    }

    MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
    IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
    if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
        if (box->borderBoxRect().contains(local)) {
            RefPtr<Node> protector(input);
            input->focus();
            input->select();
            input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1);
            event->setDefaultHandled();
            startRepeatingTimer();
        }
    } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton)
        stopRepeatingTimer();
    else if (event->type() == eventNames().mousemoveEvent) {
        if (box->borderBoxRect().contains(local)) {
            if (!m_capturing) {
                if (Frame* frame = document()->frame()) {
                    frame->eventHandler()->setCapturingMouseEventsNode(this);
                    m_capturing = true;
                }
            }
            UpDownState oldUpDownState = m_upDownState;
            m_upDownState = local.y() < box->height() / 2 ? Up : Down;
            if (m_upDownState != oldUpDownState)
                renderer()->repaint();
        } else {
            if (m_capturing) {
                stopRepeatingTimer();
                if (Frame* frame = document()->frame()) {
                    frame->eventHandler()->setCapturingMouseEventsNode(0);
                    m_capturing = false;
                }
            }
        }
    }

    if (!event->defaultHandled())
        HTMLDivElement::defaultEventHandler(event);
}
예제 #30
0
void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
{
    // Check to see if we are enclosed by a layer that requires complex painting rules.  If so, we cannot blit
    // when scrolling, and we need to use slow repaints.  Examples of layers that require this are transparent layers,
    // layers with reflections, or transformed layers.
    // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being inside
    // a transform, transparency layer, etc.
    Element* elt;
    for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) {
        RenderLayer* layer = elt->renderer()->enclosingLayer();
        if (layer->cannotBlitToWindow()) {
            frameView()->setCannotBlitToWindow();
            break;
        }

#if USE(ACCELERATED_COMPOSITING)
        if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
            if (!compositingLayer->backing()->paintsIntoWindow()) {
                frameView()->setCannotBlitToWindow();
                break;
            }
        }
#endif
    }

    if (document()->ownerElement() || !view())
        return;

    bool rootFillsViewport = false;
    Node* documentElement = document()->documentElement();
    if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
        // The document element's renderer is currently forced to be a block, but may not always be.
        RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
        rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
    }
    
    Page* page = document()->page();
    float pageScaleFactor = page ? page->pageScaleFactor() : 1;

    // If painting will entirely fill the view, no need to fill the background.
    if (rootFillsViewport && rendererObscuresBackground(firstChild()) && pageScaleFactor >= 1)
        return;

    // This code typically only executes if the root element's visibility has been set to hidden,
    // if there is a transform on the <html>, or if there is a page scale factor less than 1.
    // Only fill with the base background color (typically white) if we're the root document, 
    // since iframes/frames with no background in the child document should show the parent's background.
    if (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
        frameView()->setCannotBlitToWindow(); // The parent must show behind the child.
    else {
        Color baseColor = frameView()->baseBackgroundColor();
        if (baseColor.alpha() > 0) {
            CompositeOperator previousOperator = paintInfo.context->compositeOperation();
            paintInfo.context->setCompositeOperation(CompositeCopy);
            paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
            paintInfo.context->setCompositeOperation(previousOperator);
        } else
            paintInfo.context->clearRect(paintInfo.rect);
    }
}