Changeset 13028 in webkit


Ignore:
Timestamp:
Feb 27, 2006 4:41:39 PM (18 years ago)
Author:
justing
Message:

LayoutTests:

Reviewed by darin


Test for:
<http://bugzilla.opendarwin.org/show_bug.cgi?id=6844>
elementAtPoint returns the list when the point is over a list marker

  • fast/events/onclick-list-marker-expected.txt: Added.
  • fast/events/onclick-list-marker.html: Added.

WebCore:

Reviewed by darin


<http://bugzilla.opendarwin.org/show_bug.cgi?id=6844>
elementAtPoint returns the list when the point is over a list marker


Consider the case of outside list markers in nodeAtPoint. Had to pull
the code out of RenderListMarker::paint that computed the position/size
of the list marker.

Added:

  • fast/events/onclick-list-marker.html
  • rendering/render_list.cpp: (RenderListItem::nodeAtPoint): (RenderListItem::getAbsoluteRepaintRect): (RenderListMarker::paint): (RenderListMarker::nodeAtPoint): (RenderListMarker::getRelativeMarkerRect):
  • rendering/render_list.h:
  • rendering/render_object.h:
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r13022 r13028  
     12006-02-27  Justin Garcia  <justin.garcia@apple.com>
     2
     3        Reviewed by darin
     4       
     5        Test for:
     6        <http://bugzilla.opendarwin.org/show_bug.cgi?id=6844>
     7        elementAtPoint returns the list when the point is over a list marker
     8
     9        * fast/events/onclick-list-marker-expected.txt: Added.
     10        * fast/events/onclick-list-marker.html: Added.
     11
    1122006-02-25  Eric Seidel  <eseidel@apple.com>
    213
  • trunk/WebCore/ChangeLog

    r13027 r13028  
     12006-02-27  Justin Garcia  <justin.garcia@apple.com>
     2
     3        Reviewed by darin
     4       
     5        <http://bugzilla.opendarwin.org/show_bug.cgi?id=6844>
     6        elementAtPoint returns the list when the point is over a list marker
     7       
     8        Consider the case of outside list markers in nodeAtPoint.  Had to pull
     9        the code out of RenderListMarker::paint that computed the position/size
     10        of the list marker.
     11
     12        Added:
     13        * fast/events/onclick-list-marker.html
     14
     15        * rendering/render_list.cpp:
     16        (RenderListItem::nodeAtPoint):
     17        (RenderListItem::getAbsoluteRepaintRect):
     18        (RenderListMarker::paint):
     19        (RenderListMarker::nodeAtPoint):
     20        (RenderListMarker::getRelativeMarkerRect):
     21        * rendering/render_list.h:
     22        * rendering/render_object.h:
     23
    1242006-02-27  Eric Seidel  <eseidel@apple.com>
    225
  • trunk/WebCore/rendering/render_list.cpp

    r12977 r13028  
    289289}
    290290
     291// We need to override RenderBlock::nodeAtPoint so that a point over an outside list marker will return the list item.
     292// We should remove this when we improve the way list markers are stored in the render tree.
     293bool RenderListItem::nodeAtPoint(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
     294{
     295    if (RenderBlock::nodeAtPoint(i, x, y, tx, ty, hitTestAction))
     296        return true;
     297   
     298    if (!m_marker || m_marker->isInside() || hitTestAction != HitTestForeground)
     299        return false;
     300       
     301    return m_marker->nodeAtPoint(i, x, y, tx + m_x, ty + m_y, hitTestAction);
     302}
     303
    291304void RenderListItem::calcMinMaxWidth()
    292305{
     
    317330{
    318331    IntRect result = RenderBlock::getAbsoluteRepaintRect();
    319     if (m_marker && !m_marker->isInside()) {
    320         // This can be a sloppy and imprecise offset as long as it's always too big.
    321         int pixHeight = style()->fontDescription().computedPixelSize();
    322         int offset = pixHeight*2/3;
    323         bool haveImage = m_marker->listImage() && !m_marker->listImage()->isErrorImage();
    324         if (haveImage)
    325             offset = m_marker->listImage()->image()->width();
    326         int bulletWidth = offset/2;
    327         if (offset%2)
    328             bulletWidth++;
    329         int xoff = 0;
    330         if (style()->direction() == LTR)
    331             xoff = -cMarkerPadding - offset;
    332         else
    333             xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth));
    334 
    335         if (xoff < 0) {
    336             result.setX(result.x() + xoff);
    337             result.setWidth(result.width() - xoff);
    338         } else
    339             result.setWidth(result.width() + xoff);
     332    if (m_marker && m_marker->parent() == this && !m_marker->isInside()) {
     333        IntRect markerRect = m_marker->getRelativeMarkerRect();
     334        int x, y;
     335        absolutePosition(x, y);
     336        markerRect.move(x, y);
     337        result.unite(markerRect);
    340338    }
    341339    return result;
     
    389387    if (style()->visibility() != VISIBLE)  return;
    390388
    391     _tx += m_x;
    392     _ty += m_y;
    393 
    394     if (_ty > i.r.bottom() || _ty + m_height < i.r.y())
     389    IntRect marker = getRelativeMarkerRect();
     390    marker.move(IntPoint(_tx, _ty));
     391
     392    IntRect box(_tx + m_x, _ty + m_y, m_height, m_width);
     393
     394    if (box.y() > i.r.bottom() || box.y() + box.height() < i.r.y())
    395395        return;
    396396
    397397    if (shouldPaintBackgroundOrBorder())
    398         paintBoxDecorations(i, _tx, _ty);
     398        paintBoxDecorations(i, box.x(), box.y());
    399399
    400400    QPainter* p = i.p;
    401401    p->setFont(style()->qfont());
    402402    const QFontMetrics fm = p->fontMetrics();
    403    
    404     // The marker needs to adjust its tx, for the case where it's an outside marker.
    405     RenderObject* listItem = 0;
    406     int leftLineOffset = 0;
    407     int rightLineOffset = 0;
    408     if (!isInside()) {
    409         listItem = this;
    410         int yOffset = 0;
    411         int xOffset = 0;
    412         while (listItem && listItem != m_listItem) {
    413             yOffset += listItem->yPos();
    414             xOffset += listItem->xPos();
    415             listItem = listItem->parent();
    416         }
    417        
    418         // Now that we have our xoffset within the listbox, we need to adjust ourselves by the delta
    419         // between our current xoffset and our desired position (which is just outside the border box
    420         // of the list item).
    421         if (style()->direction() == LTR) {
    422             leftLineOffset = m_listItem->leftRelOffset(yOffset, m_listItem->leftOffset(yOffset));
    423             _tx -= (xOffset - leftLineOffset) + m_listItem->paddingLeft() + m_listItem->borderLeft();
    424         } else {
    425             rightLineOffset = m_listItem->rightRelOffset(yOffset, m_listItem->rightOffset(yOffset));
    426             _tx += (rightLineOffset-xOffset) + m_listItem->paddingRight() + m_listItem->borderRight();
    427         }
    428     }
    429403
    430404    if (p->printing()) {
    431         if (_ty < i.r.y())
     405        if (box.y() < i.r.y())
    432406            // This has been printed already we suppose.
    433407            return;
    434408       
    435409        RenderCanvas* c = canvas();
    436         if (_ty + m_height + paddingBottom() + borderBottom() >= c->printRect().bottom()) {
    437             if (_ty < c->truncatedAt())
    438                 c->setBestTruncatedAt(_ty, this);
     410        if (box.y() + box.height() + paddingBottom() + borderBottom() >= c->printRect().bottom()) {
     411            if (box.y() < c->truncatedAt())
     412                c->setBestTruncatedAt(box.y(), this);
    439413            // Let's print this on the next page.
    440414            return;
    441415        }
    442416    }
    443    
    444     int offset = fm.ascent()*2/3;
    445     bool haveImage = m_listImage && !m_listImage->isErrorImage();
    446     if (haveImage)
    447         offset = m_listImage->image()->width();
    448    
    449     int xoff = 0;
    450     int yoff = fm.ascent() - offset;
    451 
    452     int bulletWidth = offset/2;
    453     if (offset%2)
    454         bulletWidth++;
    455     if (!isInside()) {
    456         if (listItem->style()->direction() == LTR)
    457             xoff = -cMarkerPadding - offset;
    458         else
    459             xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth));
    460     } else if (style()->direction() == RTL)
    461         xoff += haveImage ? cMarkerPadding : (m_width - bulletWidth);
    462    
     417
    463418    if (m_listImage && !m_listImage->isErrorImage()) {
    464         p->drawImageAtPoint(m_listImage->image(), IntPoint(_tx + xoff, _ty));
     419        p->drawImageAtPoint(m_listImage->image(), marker.location());
    465420        return;
    466421    }
     
    468423#ifdef BOX_DEBUG
    469424    p->setPen( Qt::red );
    470     p->drawRect( _tx + xoff, _ty + yoff, offset, offset );
     425    p->drawRect(box.x(), box.y(), box.width(), box.height());
    471426#endif
    472427
     
    477432    case DISC:
    478433        p->setBrush(color);
    479         p->drawEllipse(_tx + xoff, _ty + (3 * yoff)/2, bulletWidth, bulletWidth);
     434        p->drawEllipse(marker.x(), marker.y(), marker.width(), marker.height());
    480435        return;
    481436    case CIRCLE:
    482437        p->setBrush(WebCore::Brush::NoBrush);
    483         p->drawEllipse(_tx + xoff, _ty + (3 * yoff)/2, bulletWidth, bulletWidth);
     438        p->drawEllipse(marker.x(), marker.y(), marker.width(), marker.height());
    484439        return;
    485440    case SQUARE:
    486441        p->setBrush(color);
    487         p->drawRect(_tx + xoff, _ty + (3 * yoff)/2, bulletWidth, bulletWidth);
     442        p->drawRect(marker.x(), marker.y(), marker.width(), marker.height());
    488443        return;
    489444    case LNONE:
     
    491446    default:
    492447        if (!m_item.isEmpty()) {
    493             _ty += fm.ascent();
    494 
    495448            if (isInside()) {
    496449                if( style()->direction() == LTR) {
    497                     p->drawText(_tx, _ty, 0, 0, 0, 0, Qt::AlignLeft, m_item);
    498                     p->drawText(_tx + fm.width(m_item, 0, 0), _ty, 0, 0, 0, 0, Qt::AlignLeft, ". ");
     450                    p->drawText(marker.x(), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, m_item);
     451                    p->drawText(marker.x() + fm.width(m_item, 0, 0), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, ". ");
    499452                } else {
    500                     p->drawText(_tx, _ty, 0, 0, 0, 0, Qt::AlignLeft, " .");
    501                     p->drawText(_tx + fm.width(" .", 0, 0), _ty, 0, 0, 0, 0, Qt::AlignLeft, m_item);
     453                    p->drawText(marker.x(), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, " .");
     454                    p->drawText(marker.x() + fm.width(" .", 0, 0), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, m_item);
    502455                }
    503456            } else {
    504457                if (style()->direction() == LTR) {
    505                     p->drawText(_tx - offset/2, _ty, 0, 0, 0, 0, Qt::AlignRight, ". ");
    506                     p->drawText(_tx - offset/2 - fm.width(". ", 0, 0), _ty, 0, 0, 0, 0, Qt::AlignRight, m_item);
     458                    p->drawText(marker.x(), marker.y(), 0, 0, 0, 0, Qt::AlignRight, ". ");
     459                    p->drawText(marker.x() - fm.width(". ", 0, 0), marker.y(), 0, 0, 0, 0, Qt::AlignRight, m_item);
    507460                } else {
    508                     p->drawText(_tx + offset / 2, _ty, 0, 0, 0, 0, Qt::AlignLeft, " .");
    509                     p->drawText(_tx + offset / 2 + fm.width(" .", 0, 0), _ty, 0, 0, 0, 0, Qt::AlignLeft, m_item);
     461                    p->drawText(marker.x(), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, " .");
     462                    p->drawText(marker.x() + fm.width(" .", 0, 0), marker.y(), 0, 0, 0, 0, Qt::AlignLeft, m_item);
    510463                }
    511464            }
     
    649602}
    650603
     604bool RenderListMarker::nodeAtPoint(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
     605{
     606    IntRect markerRect = getRelativeMarkerRect();
     607    markerRect.move(tx, ty);
     608    if (!markerRect.contains(x, y))
     609        return false;
     610   
     611    i.setInnerNode(m_listItem->element());
     612    return true;
     613}
     614
     615IntRect RenderListMarker::getRelativeMarkerRect()
     616{
     617    int x = m_x;
     618    int y = m_y;
     619   
     620    RenderObject* listItem = 0;
     621    int leftLineOffset = 0;
     622    int rightLineOffset = 0;
     623    if (!isInside()) {
     624        listItem = this;
     625        int yOffset = 0;
     626        int xOffset = 0;
     627        while (listItem && listItem != m_listItem) {
     628            yOffset += listItem->yPos();
     629            xOffset += listItem->xPos();
     630            listItem = listItem->parent();
     631        }
     632       
     633        // Now that we have our xoffset within the listbox, we need to adjust ourselves by the delta
     634        // between our current xoffset and our desired position (which is just outside the border box
     635        // of the list item).
     636        if (style()->direction() == LTR) {
     637            leftLineOffset = m_listItem->leftRelOffset(yOffset, m_listItem->leftOffset(yOffset));
     638            x -= (xOffset - leftLineOffset) + m_listItem->paddingLeft() + m_listItem->borderLeft();
     639        } else {
     640            rightLineOffset = m_listItem->rightRelOffset(yOffset, m_listItem->rightOffset(yOffset));
     641            x += (rightLineOffset-xOffset) + m_listItem->paddingRight() + m_listItem->borderRight();
     642        }
     643    }
     644   
     645    const QFontMetrics fm = style() ? style()->fontMetrics() : QFontMetrics();
     646   
     647    int offset = fm.ascent()*2/3;
     648    bool haveImage = m_listImage && !m_listImage->isErrorImage();
     649    if (haveImage)
     650        offset = m_listImage->image()->width();
     651   
     652    int xoff = 0;
     653    int yoff = fm.ascent() - offset;
     654
     655    int bulletWidth = offset/2;
     656    if (offset%2)
     657        bulletWidth++;
     658    if (!isInside()) {
     659        if (listItem->style()->direction() == LTR)
     660            xoff = -cMarkerPadding - offset;
     661        else
     662            xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth));
     663    } else if (style()->direction() == RTL)
     664        xoff += haveImage ? cMarkerPadding : (m_width - bulletWidth);
     665   
     666    if (m_listImage && !m_listImage->isErrorImage())
     667        return IntRect(x + xoff, y,  m_listImage->imageSize().width(), m_listImage->imageSize().height());
     668   
     669    switch(style()->listStyleType()) {
     670    case DISC:
     671    case CIRCLE:
     672    case SQUARE:
     673        return IntRect(x + xoff, y + (3 * yoff)/2, bulletWidth, bulletWidth);
     674    case LNONE:
     675        return IntRect();
     676    default:
     677        if (m_item.isEmpty())
     678            return IntRect();
     679           
     680        y += fm.ascent();
     681
     682        if (isInside())
     683            return IntRect(x, y, fm.width(m_item, 0, 0) + fm.width(". ", 0, 0), fm.height());
     684        else {
     685            if (style()->direction() == LTR)
     686                return IntRect(x - offset / 2, y, fm.width(m_item, 0, 0) + fm.width(". ", 0, 0), fm.height());
     687            else
     688                return IntRect(x + offset / 2, y, fm.width(m_item, 0, 0) + fm.width(". ", 0, 0), fm.height());
     689        }
     690    }
     691}
     692
    651693#undef BOX_DEBUG
  • trunk/WebCore/rendering/render_list.h

    r12560 r13028  
    7171
    7272    bool isInside() const;
    73 
     73   
     74    virtual bool nodeAtPoint(NodeInfo&, int, int, int, int, HitTestAction);
     75   
     76    IntRect getRelativeMarkerRect();
     77   
    7478private:
    7579    QString m_item;
     
    117121
    118122    QString markerStringValue() { return m_marker ? m_marker->text() : ""; }
     123   
     124    virtual bool nodeAtPoint(NodeInfo&, int, int, int, int, HitTestAction);
    119125
    120126private:
  • trunk/WebCore/rendering/render_object.h

    r12977 r13028  
    495495        bool active() const { return m_active; }
    496496        bool mouseMove() const { return m_mouseMove; }
    497 
    498     private:
     497       
    499498        void setInnerNode(DOM::NodeImpl* n) { m_innerNode = n; }
    500499        void setInnerNonSharedNode(DOM::NodeImpl* n) { m_innerNonSharedNode = n; }
    501500        void setURLElement(DOM::NodeImpl* n) { m_innerURLElement = n; }
    502501
     502    private:
    503503        DOM::NodeImpl* m_innerNode;
    504504        DOM::NodeImpl* m_innerNonSharedNode;
Note: See TracChangeset for help on using the changeset viewer.