Changeset 34254 in webkit


Ignore:
Timestamp:
May 29, 2008 11:05:44 PM (16 years ago)
Author:
Chris Fleizach
Message:

<rdar://problem/5091386> Seed: VO reads form labels twice in Safari
<rdar://problem/4783102> Radio button/checkbox embedded with <label> tag should combine the text and the label as a single element

Location:
trunk/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r34213 r34254  
     12008-05-29  Chris Fleizach  <cfleizach@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        <rdar://problem/4783102> Radio button/checkbox embedded with <label> tag should combine the text and the label as a single element
     6        <rdar://problem/5091386> Seed: VO reads form labels twice in Safari
     7
     8        * page/AccessibilityObject.cpp:
     9        (WebCore::AccessibilityObject::titleUIElement):
     10        * page/AccessibilityObject.h:
     11        (WebCore::AccessibilityObject::isControl):
     12        * page/AccessibilityRenderObject.cpp:
     13        (WebCore::AccessibilityRenderObject::isControl):
     14        (WebCore::AccessibilityRenderObject::labelElementContainer):
     15        (WebCore::AccessibilityRenderObject::title):
     16        (WebCore::AccessibilityRenderObject::checkboxOrRadioRect):
     17        (WebCore::AccessibilityRenderObject::elementRect):
     18        (WebCore::AccessibilityRenderObject::titleUIElement):
     19        (WebCore::AccessibilityRenderObject::accessibilityIsIgnored):
     20        (WebCore::AccessibilityRenderObject::roleValue):
     21        * page/AccessibilityRenderObject.h:
     22        * page/mac/AccessibilityObjectWrapper.mm:
     23        (-[AccessibilityObjectWrapper accessibilityAttributeNames]):
     24        (-[AccessibilityObjectWrapper accessibilityAttributeValue:]):
     25
    1262008-05-29  Timothy Hatcher  <timothy@apple.com>
    227
  • trunk/WebCore/page/AccessibilityObject.cpp

    r33937 r34254  
    208208    return 0;
    209209}
     210   
     211AccessibilityObject* AccessibilityObject::titleUIElement() const
     212{
     213     return 0;   
     214}
    210215
    211216int AccessibilityObject::textLength() const
  • trunk/WebCore/page/AccessibilityObject.h

    r34129 r34254  
    211211    virtual bool isFileUploadButton() const { return false; };
    212212    virtual bool isProgressIndicator() const { return false; };
     213    virtual bool isControl() const { return false; };
    213214   
    214215    virtual bool isChecked() const { return false; };
     
    253254    virtual AccessibilityObject* observableObject() const;
    254255    virtual AccessibilityObject* linkedUIElement() const;
     256    virtual AccessibilityObject* titleUIElement() const;
    255257    virtual AccessibilityRole ariaRoleAttribute() const;
    256258    virtual AccessibilityRole roleValue() const;
  • trunk/WebCore/page/AccessibilityRenderObject.cpp

    r34129 r34254  
    406406    return roleValue() == WebCoreLinkRole;
    407407}   
     408   
     409bool AccessibilityRenderObject::isControl() const
     410{
     411    if (!m_renderer)
     412        return false;
     413   
     414    Node* node = m_renderer->element();
     415    return node && (node->isControl() || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
     416}
    408417
    409418const AtomicString& AccessibilityRenderObject::getAttribute(const QualifiedName& attribute) const
     
    780789    return 0;
    781790}
     791   
     792HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const
     793{
     794    if (!m_renderer)
     795        return false;
     796
     797    // the control element should not be considered part of the label
     798    if (isControl())
     799        return false;
     800   
     801    // find if this has a parent that is a label
     802    for (Node* parentNode = m_renderer->element(); parentNode; parentNode = parentNode->parentNode()) {
     803        if (parentNode->hasTagName(labelTag))
     804            return static_cast<HTMLLabelElement*>(parentNode);
     805    }
     806   
     807    return 0;
     808}
    782809
    783810String AccessibilityRenderObject::title() const
     
    807834    }
    808835   
    809     if (isInputTag || AccessibilityObject::isARIAInput(ariaRole)) {
     836    if (isInputTag || AccessibilityObject::isARIAInput(ariaRole) || isControl()) {
    810837        HTMLLabelElement* label = labelForElement(static_cast<Element*>(node));
    811838        if (label)
     
    897924    return rect;
    898925}
     926   
     927IntRect AccessibilityRenderObject::checkboxOrRadioRect() const
     928{
     929    if (!m_renderer)
     930        return IntRect();
     931   
     932    HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->element()));
     933    if (!label || !label->renderer())
     934        return IntRect();
     935   
     936    IntRect labelRect = axObjectCache()->get(label->renderer())->elementRect();
     937    labelRect.unite(boundingBoxRect());
     938    return labelRect;
     939}
    899940
    900941IntRect AccessibilityRenderObject::elementRect() const
     
    902943    if (m_areaElement)
    903944        return m_areaElement->getRect(m_renderer);
     945   
     946    // a checkbox or radio button should encompass its label
     947    if (isCheckboxOrRadio())
     948        return checkboxOrRadioRect();
    904949   
    905950    return boundingBoxRect();
     
    951996}
    952997
     998AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
     999{
     1000    if (!m_renderer)
     1001        return 0;
     1002   
     1003    // checkbox and radio hide their labels. Only controls get titleUIElements for now
     1004    if (isCheckboxOrRadio() || !isControl())
     1005        return 0;
     1006   
     1007    Node* element = m_renderer->element();
     1008    HTMLLabelElement* label = labelForElement(static_cast<Element*>(element));
     1009    if (label && label->renderer())
     1010        return axObjectCache()->get(label->renderer());
     1011
     1012    return 0;   
     1013}
     1014   
    9531015bool AccessibilityRenderObject::accessibilityIsIgnored() const
    9541016{
     
    9661028    }
    9671029   
     1030    // find out if this element is inside of a label element.
     1031    // if so, it may be ignored because it's the label for a checkbox or radio button
     1032    HTMLLabelElement* labelElement = labelElementContainer();
     1033    if (labelElement) {
     1034        HTMLElement* correspondingControl = labelElement->correspondingControl();
     1035        if (correspondingControl && correspondingControl->renderer()) {
     1036            AccessibilityObject* controlObject = axObjectCache()->get(correspondingControl->renderer());
     1037            if (controlObject->isCheckboxOrRadio())
     1038                return true;
     1039        }
     1040    }
     1041       
    9681042    AccessibilityRole ariaRole = ariaRoleAttribute();
    9691043    if (ariaRole == TextAreaRole || ariaRole == StaticTextRole) {
     
    9881062   
    9891063    // all controls are accessible
    990     if (m_renderer->element() && (m_renderer->element()->isControl() || AccessibilityObject::isARIAControl(ariaRoleAttribute())))
     1064    if (isControl())
     1065        return false;
     1066   
     1067    // don't ignore labels, because they serve as TitleUIElements
     1068    Node* node = m_renderer->element();
     1069    if (node && node->hasTagName(labelTag))
    9911070        return false;
    9921071   
     
    9961075    // ignore images seemingly used as spacers
    9971076    if (isImage()) {
    998         Node* node = m_renderer->element();
    9991077        if (node && node->isElementNode()) {
    10001078            Element* elt = static_cast<Element*>(node);
     
    19171995        return HeadingRole;
    19181996   
    1919     if (m_renderer->isBlockFlow())
     1997    if (m_renderer->isBlockFlow() || node->hasTagName(labelTag))
    19201998        return GroupRole;
    19211999   
  • trunk/WebCore/page/AccessibilityRenderObject.h

    r34129 r34254  
    4242class HTMLAreaElement;
    4343class HTMLElement;
     44class HTMLLabelElement;
    4445class HTMLSelectElement;
    4546class IntPoint;
     
    8182    virtual bool isMenuButton() const;
    8283    virtual bool isMenuItem() const;
     84    virtual bool isControl() const;
    8385
    8486    virtual bool isEnabled() const;
     
    120122    virtual AccessibilityObject* observableObject() const;
    121123    virtual AccessibilityObject* linkedUIElement() const;
     124    virtual AccessibilityObject* titleUIElement() const;
    122125    virtual AccessibilityRole ariaRoleAttribute() const;
    123126    void setAriaRole();
     
    143146    Document* document() const;
    144147    FrameView* topDocumentFrameView() const; 
     148    HTMLLabelElement* labelElementContainer() const;
    145149   
    146150    virtual KURL url() const;
     
    217221    AccessibilityRole determineAriaRoleAttribute() const;
    218222
     223    IntRect checkboxOrRadioRect() const;
     224   
    219225};
    220226   
  • trunk/WebCore/page/mac/AccessibilityObjectWrapper.mm

    r34058 r34254  
    537537    static NSArray* menuItemAttrs = nil;
    538538    static NSArray* menuButtonAttrs = nil;
     539    static NSArray* controlAttrs = nil;
    539540    NSMutableArray* tempArray;
    540541    if (attributes == nil) {
     
    594595        [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
    595596        [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
     597        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
    596598        textAttrs = [[NSArray alloc] initWithArray:tempArray];
    597599        [tempArray release];
     
    602604        [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
    603605        [tempArray addObject:NSAccessibilityOrientationAttribute];
     606        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
    604607        listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
    605608        [tempArray release];
     
    658661            NSAccessibilityChildrenAttribute, nil];
    659662    }
     663    if (controlAttrs == nil) {
     664        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
     665        [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
     666        controlAttrs = [[NSArray alloc] initWithArray:tempArray];
     667        [tempArray release];
     668    }
    660669
    661670    if (m_object->isPasswordField())
     
    677686        return progressIndicatorAttrs;
    678687
     688    if (m_object->isControl())
     689        return controlAttrs;
     690   
    679691    if (m_object->isMenu())
    680692        return menuAttrs;
     
    11041116    }
    11051117
     1118    if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
     1119        AccessibilityObject* obj = m_object->titleUIElement();
     1120        if (obj)
     1121            return obj->wrapper();
     1122        return nil;
     1123    }
     1124   
    11061125    return nil;
    11071126}
Note: See TracChangeset for help on using the changeset viewer.