Changeset 220313 in webkit


Ignore:
Timestamp:
Aug 5, 2017 1:08:16 AM (7 years ago)
Author:
Carlos Garcia Campos
Message:

getClientRects doesn't work with list box option elements
https://bugs.webkit.org/show_bug.cgi?id=175016

Reviewed by Darin Adler.

Source/WebCore:

Since HTMLOptionElement and HTMLOptGroupElement don't have a renderer, we are always returning an empty list
from getClientRects. This is working fine in both chromium and firefox, option elements return its own bounding
box and group elements return the bounding box of the group label and all its children items.

Test: fast/dom/HTMLSelectElement/listbox-items-client-rects.html

  • dom/Element.cpp:

(WebCore::listBoxElementBoundingBox): Helper function to return the bounding box of a HTMLOptionElement or
HTMLOptGroupElement element.
(WebCore::Element::getClientRects): Use listBoxElementBoundingBox() in case of HTMLOptionElement or
HTMLOptGroupElement.
(WebCore::Element::boundingClientRect): Ditto.

LayoutTests:

Add new test to check list box option elements client rects.

  • fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
  • fast/dom/HTMLSelectElement/listbox-items-client-rects.html: Added.
  • platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
Location:
trunk
Files:
6 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r220311 r220313  
     12017-08-05  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        getClientRects doesn't work with list box option elements
     4        https://bugs.webkit.org/show_bug.cgi?id=175016
     5
     6        Reviewed by Darin Adler.
     7
     8        Add new test to check list box option elements client rects.
     9
     10        * fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
     11        * fast/dom/HTMLSelectElement/listbox-items-client-rects.html: Added.
     12        * platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
     13
    1142017-08-04  Youenn Fablet  <youenn@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r220311 r220313  
     12017-08-05  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        getClientRects doesn't work with list box option elements
     4        https://bugs.webkit.org/show_bug.cgi?id=175016
     5
     6        Reviewed by Darin Adler.
     7
     8        Since HTMLOptionElement and HTMLOptGroupElement don't have a renderer, we are always returning an empty list
     9        from getClientRects. This is working fine in both chromium and firefox, option elements return its own bounding
     10        box and group elements return the bounding box of the group label and all its children items.
     11
     12        Test: fast/dom/HTMLSelectElement/listbox-items-client-rects.html
     13
     14        * dom/Element.cpp:
     15        (WebCore::listBoxElementBoundingBox): Helper function to return the bounding box of a HTMLOptionElement or
     16        HTMLOptGroupElement element.
     17        (WebCore::Element::getClientRects): Use listBoxElementBoundingBox() in case of HTMLOptionElement or
     18        HTMLOptGroupElement.
     19        (WebCore::Element::boundingClientRect): Ditto.
     20
    1212017-08-04  Youenn Fablet  <youenn@apple.com>
    222
  • trunk/Source/WebCore/dom/Element.cpp

    r220202 r220313  
    6262#include "HTMLNameCollection.h"
    6363#include "HTMLObjectElement.h"
     64#include "HTMLOptGroupElement.h"
     65#include "HTMLOptionElement.h"
    6466#include "HTMLParserIdioms.h"
     67#include "HTMLSelectElement.h"
    6568#include "HTMLTemplateElement.h"
    6669#include "IdChangeInvalidation.h"
     
    7982#include "RenderFlowThread.h"
    8083#include "RenderLayer.h"
     84#include "RenderListBox.h"
    8185#include "RenderNamedFlowFragment.h"
    8286#include "RenderRegion.h"
     
    11461150}
    11471151
     1152static std::optional<std::pair<RenderObject*, LayoutRect>> listBoxElementBoundingBox(Element& element)
     1153{
     1154    HTMLSelectElement* selectElement;
     1155    bool isGroup;
     1156    if (is<HTMLOptionElement>(element)) {
     1157        selectElement = downcast<HTMLOptionElement>(element).ownerSelectElement();
     1158        isGroup = false;
     1159    } else if (is<HTMLOptGroupElement>(element)) {
     1160        selectElement = downcast<HTMLOptGroupElement>(element).ownerSelectElement();
     1161        isGroup = true;
     1162    } else
     1163        return std::nullopt;
     1164
     1165    if (!selectElement || !selectElement->renderer() || !is<RenderListBox>(selectElement->renderer()))
     1166        return std::nullopt;
     1167
     1168    auto& renderer = downcast<RenderListBox>(*selectElement->renderer());
     1169    std::optional<LayoutRect> boundingBox;
     1170    int optionIndex = 0;
     1171    for (auto* item : selectElement->listItems()) {
     1172        if (item == &element) {
     1173            LayoutPoint additionOffset;
     1174            boundingBox = renderer.itemBoundingBoxRect(additionOffset, optionIndex);
     1175            if (!isGroup)
     1176                break;
     1177        } else if (isGroup && boundingBox) {
     1178            if (item->parentNode() != &element)
     1179                break;
     1180            LayoutPoint additionOffset;
     1181            boundingBox->setHeight(boundingBox->height() + renderer.itemBoundingBoxRect(additionOffset, optionIndex).height());
     1182        }
     1183        ++optionIndex;
     1184    }
     1185
     1186    if (!boundingBox)
     1187        return std::nullopt;
     1188
     1189    return std::pair<RenderObject*, LayoutRect> { &renderer, boundingBox.value() };
     1190}
     1191
    11481192Ref<DOMRectList> Element::getClientRects()
    11491193{
    11501194    document().updateLayoutIgnorePendingStylesheets();
    11511195
    1152     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
    1153     if (!renderBoxModelObject)
    1154         return DOMRectList::create();
     1196    RenderObject* renderer = this->renderer();
     1197    Vector<FloatQuad> quads;
     1198
     1199    if (auto pair = listBoxElementBoundingBox(*this)) {
     1200        renderer = pair.value().first;
     1201        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
     1202    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
     1203        renderBoxModelObject->absoluteQuads(quads);
    11551204
    11561205    // FIXME: Handle SVG elements.
    11571206    // FIXME: Handle table/inline-table with a caption.
    11581207
     1208    if (quads.isEmpty())
     1209        return DOMRectList::create();
     1210
     1211    document().convertAbsoluteToClientQuads(quads, renderer->style());
     1212    return DOMRectList::create(quads);
     1213}
     1214
     1215FloatRect Element::boundingClientRect()
     1216{
     1217    document().updateLayoutIgnorePendingStylesheets();
     1218
     1219    RenderObject* renderer = this->renderer();
    11591220    Vector<FloatQuad> quads;
    1160     renderBoxModelObject->absoluteQuads(quads);
    1161     document().convertAbsoluteToClientQuads(quads, renderBoxModelObject->style());
    1162     return DOMRectList::create(quads);
    1163 }
    1164 
    1165 FloatRect Element::boundingClientRect()
    1166 {
    1167     document().updateLayoutIgnorePendingStylesheets();
    1168 
    1169     Vector<FloatQuad> quads;
    1170     if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
     1221    if (isSVGElement() && renderer && !renderer->isSVGRoot()) {
    11711222        // Get the bounding rectangle from the SVG model.
    11721223        SVGElement& svgElement = downcast<SVGElement>(*this);
    11731224        FloatRect localRect;
    11741225        if (svgElement.getBoundingBox(localRect))
    1175             quads.append(renderer()->localToAbsoluteQuad(localRect));
    1176     } else {
    1177         // Get the bounding rectangle from the box model.
    1178         if (renderBoxModelObject())
    1179             renderBoxModelObject()->absoluteQuads(quads);
    1180     }
     1226            quads.append(renderer->localToAbsoluteQuad(localRect));
     1227    } else if (auto pair = listBoxElementBoundingBox(*this)) {
     1228        renderer = pair.value().first;
     1229        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
     1230    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
     1231        renderBoxModelObject->absoluteQuads(quads);
    11811232
    11821233    if (quads.isEmpty())
     
    11871238        result.unite(quads[i].boundingBox());
    11881239
    1189     document().convertAbsoluteToClientRect(result, renderer()->style());
     1240    document().convertAbsoluteToClientRect(result, renderer->style());
    11901241    return result;
    11911242}
Note: See TracChangeset for help on using the changeset viewer.