WebCore:
authorbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Jul 2008 00:10:13 +0000 (00:10 +0000)
committerbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Jul 2008 00:10:13 +0000 (00:10 +0000)
2008-07-02  Beth Dakin  <bdakin@apple.com>

        Reviewed by Darin.

        Fix for <rdar://problem/6015523> Implement ARIA ranges/sliders
        and
        <rdar://problem/5934355> Need to implement ARIA role="spinbutton"

        * page/AccessibilityObject.h:
        (WebCore::AccessibilityObject::isSlider):
        * page/AccessibilityRenderObject.cpp:
        (WebCore::AccessibilityRenderObject::isSlider):
        (WebCore::AccessibilityRenderObject::valueForRange):
        (WebCore::AccessibilityRenderObject::maxValueForRange):
        (WebCore::AccessibilityRenderObject::minValueForRange):
        (WebCore::AccessibilityRenderObject::accessibilityIsIgnored): We
        were addressing the generic has-an-ARIA-role case too early here.
        (WebCore::AccessibilityRenderObject::focusedUIElement): This is a
        bug I ran into while testing role='spinbutton', spinbutton is a
        role that can have an active descendant. But we were always trying
        to forward focus to the active descendant, even if one was not
        specified.
        (WebCore::AccessibilityRenderObject::shouldFocusActiveDescendant):
        'spinbutton' maps to ProgressIndicatorRole.
        (WebCore::RoleEntry::):
        (WebCore::AccessibilityRenderObject::canSetValueAttribute):
        * page/AccessibilityRenderObject.h:
        * page/mac/AccessibilityObjectWrapper.mm:
        (-[AccessibilityObjectWrapper accessibilityAttributeNames]):
        (-[AccessibilityObjectWrapper accessibilityAttributeValue:]):

LayoutTests:

2008-07-02  Beth Dakin  <bdakin@apple.com>

        Reviewed by Darin.

        Tests for <rdar://problem/6015523> Implement ARIA ranges/sliders
        and
        <rdar://problem/5934355> Need to implement ARIA role="spinbutton"

        * accessibility/aria-range-expected.txt: Added.
        * accessibility/aria-range.html: Added.
        * accessibility/aria-slider-expected.txt: Added.
        * accessibility/aria-slider.html: Added.
        * accessibility/aria-spinbutton-expected.txt: Added.
        * accessibility/aria-spinbutton.html: Added.

        This test used to have a section for slider. It was a mistake for
        that to be checked in since slider was not implemented until not.
        * accessibility/aria-roles-expected.txt:
        * accessibility/aria-roles.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34963 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/accessibility/aria-range-expected.txt [new file with mode: 0644]
LayoutTests/accessibility/aria-range.html [new file with mode: 0644]
LayoutTests/accessibility/aria-roles-expected.txt
LayoutTests/accessibility/aria-roles.html
LayoutTests/accessibility/aria-slider-expected.txt [new file with mode: 0644]
LayoutTests/accessibility/aria-slider.html [new file with mode: 0644]
LayoutTests/accessibility/aria-spinbutton-expected.txt [new file with mode: 0644]
LayoutTests/accessibility/aria-spinbutton.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/page/AccessibilityObject.h
WebCore/page/AccessibilityRenderObject.cpp
WebCore/page/AccessibilityRenderObject.h
WebCore/page/mac/AccessibilityObjectWrapper.mm

index b8ee1e7acf7cbe93dd5369853243e57b5ad80ce0..eb69d62ced705c533fa88eaad7b4a9a5704048ce 100644 (file)
@@ -1,3 +1,23 @@
+2008-07-02  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Darin.
+
+        Tests for <rdar://problem/6015523> Implement ARIA ranges/sliders
+        and
+        <rdar://problem/5934355> Need to implement ARIA role="spinbutton"
+
+        * accessibility/aria-range-expected.txt: Added.
+        * accessibility/aria-range.html: Added.
+        * accessibility/aria-slider-expected.txt: Added.
+        * accessibility/aria-slider.html: Added.
+        * accessibility/aria-spinbutton-expected.txt: Added.
+        * accessibility/aria-spinbutton.html: Added.
+
+        This test used to have a section for slider. It was a mistake for 
+        that to be checked in since slider was not implemented until not. 
+        * accessibility/aria-roles-expected.txt:
+        * accessibility/aria-roles.html:
+
 2008-07-02  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
 
         Reviewed by Darin.
diff --git a/LayoutTests/accessibility/aria-range-expected.txt b/LayoutTests/accessibility/aria-range-expected.txt
new file mode 100644 (file)
index 0000000..1ea5103
--- /dev/null
@@ -0,0 +1,5 @@
+In accessibility, the following should be a progress indicator:
+
+X
+
+This test PASSES in DumpRenderTree. The role is AXRole: AXSlider
diff --git a/LayoutTests/accessibility/aria-range.html b/LayoutTests/accessibility/aria-range.html
new file mode 100644 (file)
index 0000000..e87fc33
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<body>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    function validateRole() {
+        if (!window.accessibilityController)
+            return;
+        
+        var aria = document.getElementById("range");
+        aria.focus();
+        var ariaRole = accessibilityController.roleOfFocusedElement();
+       
+        var result = document.getElementById("result");
+        if (ariaRole == "AXRole: AXSlider")
+            result.innerText = "This test PASSES in DumpRenderTree. The role is " + ariaRole;
+        else
+            result.innerText = "This test FAILS in DumpRenderTree. The ARIA role is " + ariaRole + ", but should be AXSlider";
+    }
+</script>
+
+<div>
+    <p>In accessibility, the following should be a progress indicator:</p>
+    <p><span tabindex="0" role="range" id="range" aria-valuenow=5 aria-valuemin=0 aria-valuemax=10>X</span></p>
+    <span id="result"></span>
+    <script>
+        validateRole();
+    </script>
+  </div>
+  
+ </body>
+</html>
index 683b03b3e0063482f88140dbe200d446d69316d4..0049df4e58c171d01629d902d3219265ffd78dc2 100644 (file)
@@ -70,12 +70,4 @@ Broccoli
 Beets
 This test PASSES in DumpRenderTree. The role is AXRole: AXGroup
 
-The following should be a slider:
-
-X
-
-Actual slider:
-
- This test PASSES in DumpRenderTree. The role is AXRole: AXGroup
-
 
index c8b4c4673e220b4df6b4dc32ca058faf046a6914..83cc6ed7791b9e5300be2d0b39970e3098534965 100644 (file)
   </div>
   <br/>
 
-  <!--Slider-->
-  <div class="newRole">
-    <p>The following should be a slider:</p>
-    <p><span tabindex="0" role="slider" id="ariaSlider">X</span></p>
-    <p>Actual slider:</p>
-    <input type="range" tabindex=0 id="realSlider"></input>
-    <span id="resultSlider"></span>
-    <script>
-        validateRole(document.getElementById('ariaSlider'),
-            document.getElementById('realSlider'),
-            document.getElementById('resultSlider'));
-    </script>
-  </div>
-  <br/>
-
  </body>
 </html>
diff --git a/LayoutTests/accessibility/aria-slider-expected.txt b/LayoutTests/accessibility/aria-slider-expected.txt
new file mode 100644 (file)
index 0000000..1ea5103
--- /dev/null
@@ -0,0 +1,5 @@
+In accessibility, the following should be a progress indicator:
+
+X
+
+This test PASSES in DumpRenderTree. The role is AXRole: AXSlider
diff --git a/LayoutTests/accessibility/aria-slider.html b/LayoutTests/accessibility/aria-slider.html
new file mode 100644 (file)
index 0000000..e563350
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<body>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    function validateRole() {
+        if (!window.accessibilityController)
+            return;
+        
+        var aria = document.getElementById("slider");
+        aria.focus();
+        var ariaRole = accessibilityController.roleOfFocusedElement();
+       
+        var result = document.getElementById("result");
+        if (ariaRole == "AXRole: AXSlider")
+            result.innerText = "This test PASSES in DumpRenderTree. The role is " + ariaRole;
+        else
+            result.innerText = "This test FAILS in DumpRenderTree. The ARIA role is " + ariaRole + ", but should be AXSlider";
+    }
+</script>
+
+<div>
+    <p>In accessibility, the following should be a progress indicator:</p>
+    <p><span tabindex="0" role="slider" id="slider" aria-valuenow=5 aria-valuemin=0 aria-valuemax=10>X</span></p>
+    <span id="result"></span>
+    <script>
+        validateRole();
+    </script>
+  </div>
+  
+ </body>
+</html>
diff --git a/LayoutTests/accessibility/aria-spinbutton-expected.txt b/LayoutTests/accessibility/aria-spinbutton-expected.txt
new file mode 100644 (file)
index 0000000..fab3d0e
--- /dev/null
@@ -0,0 +1,5 @@
+In accessibility, the following should be a progress indicator:
+
+X
+
+This test PASSES in DumpRenderTree. The role is AXRole: AXProgressIndicator
diff --git a/LayoutTests/accessibility/aria-spinbutton.html b/LayoutTests/accessibility/aria-spinbutton.html
new file mode 100644 (file)
index 0000000..c9c96da
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<body>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    function validateRole() {
+        if (!window.accessibilityController)
+            return;
+        
+        var aria = document.getElementById("spinbutton");
+        aria.focus();
+        var ariaRole = accessibilityController.roleOfFocusedElement();
+       
+        var result = document.getElementById("result");
+        if (ariaRole == "AXRole: AXProgressIndicator")
+            result.innerText = "This test PASSES in DumpRenderTree. The role is " + ariaRole;
+        else
+            result.innerText = "This test FAILS in DumpRenderTree. The ARIA role is " + ariaRole + ", but should be AXProgressIndicator";
+    }
+</script>
+
+<div>
+    <p>In accessibility, the following should be a progress indicator:</p>
+    <p><span tabindex="0" role="spinbutton" id="spinbutton" aria-valuenow=5 aria-valuemin=0 aria-valuemax=10>X</span></p>
+    <span id="result"></span>
+    <script>
+        validateRole();
+    </script>
+  </div>
+  
+ </body>
+</html>
index 134b49e58b623079cc5c46d88cbb1947ff569eda..8da42084f18784a3383ee931295855afbfb4d5cc 100644 (file)
@@ -1,3 +1,34 @@
+2008-07-02  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Darin.
+
+        Fix for <rdar://problem/6015523> Implement ARIA ranges/sliders
+        and
+        <rdar://problem/5934355> Need to implement ARIA role="spinbutton"
+
+        * page/AccessibilityObject.h:
+        (WebCore::AccessibilityObject::isSlider):
+        * page/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::isSlider):
+        (WebCore::AccessibilityRenderObject::valueForRange):
+        (WebCore::AccessibilityRenderObject::maxValueForRange):
+        (WebCore::AccessibilityRenderObject::minValueForRange):
+        (WebCore::AccessibilityRenderObject::accessibilityIsIgnored): We 
+        were addressing the generic has-an-ARIA-role case too early here.
+        (WebCore::AccessibilityRenderObject::focusedUIElement): This is a 
+        bug I ran into while testing role='spinbutton', spinbutton is a 
+        role that can have an active descendant. But we were always trying 
+        to forward focus to the active descendant, even if one was not 
+        specified. 
+        (WebCore::AccessibilityRenderObject::shouldFocusActiveDescendant): 
+        'spinbutton' maps to ProgressIndicatorRole.
+        (WebCore::RoleEntry::):
+        (WebCore::AccessibilityRenderObject::canSetValueAttribute):
+        * page/AccessibilityRenderObject.h:
+        * page/mac/AccessibilityObjectWrapper.mm:
+        (-[AccessibilityObjectWrapper accessibilityAttributeNames]):
+        (-[AccessibilityObjectWrapper accessibilityAttributeValue:]):
+
 2008-07-02  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Adam Roben.
index 661ef9832fb230d5adbb1c7f87f02adb5320ed48..03fbf4c70ba67e9c891145888b04a87ab92fa204 100644 (file)
@@ -208,6 +208,7 @@ public:
     virtual bool isMenuItem() const { return false; }
     virtual bool isFileUploadButton() const { return false; };
     virtual bool isProgressIndicator() const { return false; };
+    virtual bool isSlider() const { return false; };
     virtual bool isControl() const { return false; };
     
     virtual bool isChecked() const { return false; };
index 5b13d97404c765b6ac7864fb11492050fb53b9d3..df3a3b3ae04f88fb914762c13166d0cca34bb7eb 100644 (file)
@@ -253,6 +253,11 @@ bool AccessibilityRenderObject::isProgressIndicator() const
 {
     return roleValue() == ProgressIndicatorRole;
 }
+
+bool AccessibilityRenderObject::isSlider() const
+{
+    return roleValue() == SliderRole;
+}
     
 bool AccessibilityRenderObject::isMenuRelated() const
 {
@@ -641,7 +646,7 @@ int AccessibilityRenderObject::intValue() const
 
 float AccessibilityRenderObject::valueForRange() const
 {
-    if (!isProgressIndicator())
+    if (!isProgressIndicator() && !isSlider())
         return 0.0f;
 
     return getAttribute(aria_valuenowAttr).toFloat();
@@ -649,7 +654,7 @@ float AccessibilityRenderObject::valueForRange() const
 
 float AccessibilityRenderObject::maxValueForRange() const
 {
-    if (!isProgressIndicator())
+    if (!isProgressIndicator() && !isSlider())
         return 0.0f;
 
     return getAttribute(aria_valuemaxAttr).toFloat();
@@ -657,7 +662,7 @@ float AccessibilityRenderObject::maxValueForRange() const
 
 float AccessibilityRenderObject::minValueForRange() const
 {
-    if (!isProgressIndicator())
+    if (!isProgressIndicator() && !isSlider())
         return 0.0f;
 
     return getAttribute(aria_valueminAttr).toFloat();
@@ -1064,9 +1069,6 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
     if (!m_renderer || m_renderer->style()->visibility() != VISIBLE)
         return true;
 
-    if (ariaRoleAttribute() != UnknownRole)
-        return false;
-    
     if (isPresentationalChildOfAriaRole())
         return true;
         
@@ -1149,6 +1151,9 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
         return false;
     }
     
+    if (ariaRole != UnknownRole)
+        return false;
+    
     if (isAttachment())
         return false;
     
@@ -1831,8 +1836,10 @@ AccessibilityObject* AccessibilityRenderObject::focusedUIElement() const
     
     AccessibilityObject* obj = focusedNodeRenderer->document()->axObjectCache()->get(focusedNodeRenderer);
     
-    if (obj->shouldFocusActiveDescendant())
-        obj = obj->activeDescendant();
+    if (obj->shouldFocusActiveDescendant()) {
+        if (AccessibilityObject* descendant = obj->activeDescendant())
+            obj = descendant;
+    }
     
     // the HTML element, for example, is focusable but has an AX object that is ignored
     if (obj->accessibilityIsIgnored())
@@ -1860,7 +1867,6 @@ bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
     alert
     alertdialog
     grid
-    spinbutton
     status
     timer
     tree
@@ -1925,22 +1931,25 @@ static const ARIARoleMap& createARIARoleMap()
     };
 
     static const RoleEntry roles[] = {
-        { String("button"), ButtonRole },
-        { String("checkbox"), CheckBoxRole },
-        { String("heading"), HeadingRole },
-        { String("img"), ImageRole },
-        { String("link"), WebCoreLinkRole },
-        { String("progressbar"), ProgressIndicatorRole },
-        { String("radio"), RadioButtonRole },
-        { String("textbox"), TextAreaRole },
-        { String("listbox"), ListBoxRole },
-         // "option" isn't here because it may map to different roles depending on the parent element's role
-        { String("menu"), MenuRole },
-        { String("menubar"), GroupRole },
+        { "button", ButtonRole },
+        { "checkbox", CheckBoxRole },
+        { "group", GroupRole },
+        { "heading", HeadingRole },
+        { "img", ImageRole },
+        { "link", WebCoreLinkRole },
+        { "listbox", ListBoxRole },
+        // "option" isn't here because it may map to different roles depending on the parent element's role
+        { "menu", MenuRole },
+        { "menubar", GroupRole },
         // "menuitem" isn't here because it may map to different roles depending on the parent element's role
-        { String("menuitemcheckbox"), MenuItemRole },
-        { String("menuitemradio"), MenuItemRole },
-        { String("group"), GroupRole }
+        { "menuitemcheckbox", MenuItemRole },
+        { "menuitemradio", MenuItemRole },
+        { "progressbar", ProgressIndicatorRole },
+        { "radio", RadioButtonRole },
+        { "range", SliderRole },
+        { "slider", SliderRole },
+        { "spinbutton", ProgressIndicatorRole },
+        { "textbox", TextAreaRole }
     };
     ARIARoleMap& roleMap = *new ARIARoleMap;
         
@@ -2157,7 +2166,7 @@ bool AccessibilityRenderObject::canSetValueAttribute() const
     if (isWebArea()) 
         return !isReadOnly();
 
-    return isTextControl() || isProgressIndicator();
+    return isTextControl() || isProgressIndicator() || isSlider();
 }
 
 bool AccessibilityRenderObject::canSetTextRangeAttributes() const
index 298ab4be2294e0ae7e8f7c268c7ab67e4d0ef852..d3cffd4889e3cebf37da4cf0786eb1b9cabf4b6c 100644 (file)
@@ -76,6 +76,7 @@ public:
     virtual bool isCheckboxOrRadio() const;
     virtual bool isFileUploadButton() const;
     virtual bool isProgressIndicator() const;
+    virtual bool isSlider() const;
     virtual bool isMenuRelated() const;
     virtual bool isMenu() const;
     virtual bool isMenuBar() const;
index 2cc086381bb41a217a51c61771a383532e47c190..9c62730ee405a3548c3c5ee95d8ca022ae36d1a2 100644 (file)
@@ -534,7 +534,7 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
     static NSArray* webAreaAttrs = nil;
     static NSArray* textAttrs = nil;
     static NSArray* listBoxAttrs = nil;
-    static NSArray* progressIndicatorAttrs = nil;
+    static NSArray* rangeAttrs = nil;
     static NSArray* commonMenuAttrs = nil;
     static NSArray* menuAttrs = nil;
     static NSArray* menuBarAttrs = nil;
@@ -611,13 +611,13 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
         [tempArray release];
     }
-    if (progressIndicatorAttrs == nil) {
+    if (rangeAttrs == nil) {
         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
         [tempArray addObject:NSAccessibilityTopLevelUIElementAttribute];
         [tempArray addObject:NSAccessibilityValueAttribute];
         [tempArray addObject:NSAccessibilityMinValueAttribute];
         [tempArray addObject:NSAccessibilityMaxValueAttribute];
-        progressIndicatorAttrs = [[NSArray alloc] initWithArray:tempArray];
+        rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
         [tempArray release];
     }
     if (menuBarAttrs == nil) {
@@ -686,8 +686,8 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
     if (m_object->isListBox())
         return listBoxAttrs;
 
-    if (m_object->isProgressIndicator())
-        return progressIndicatorAttrs;
+    if (m_object->isProgressIndicator() || m_object->isSlider())
+        return rangeAttrs;
 
     if (m_object->isControl())
         return controlAttrs;
@@ -1056,7 +1056,7 @@ static NSString* roleValueToNSString(AccessibilityRole value)
             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) 
                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
         }
-        if (m_object->isProgressIndicator())
+        if (m_object->isProgressIndicator() || m_object->isSlider())
             return [NSNumber numberWithFloat:m_object->valueForRange()];
         if (m_object->hasIntValue())
             return [NSNumber numberWithInt:m_object->intValue()];