AX: buttons of number type <input> controls are not fully accessible
authorcfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Oct 2011 23:37:59 +0000 (23:37 +0000)
committercfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Oct 2011 23:37:59 +0000 (23:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=70241

Source/WebCore:

Expose the spin button object to the AX hierarchy. Since there is no distinct
render object that backs this object, a mock object needs to be created for the entire
spin button and the actual increment and decrement buttons inside.

Reviewed by Darin Adler.

Test: platform/mac/accessibility/html5-input-number.html

* CMakeLists.txt:
* GNUmakefile.list.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::getOrCreate):
* accessibility/AccessibilityMockObject.cpp:
(WebCore::AccessibilityMockObject::AccessibilityMockObject):
* accessibility/AccessibilityMockObject.h:
(WebCore::AccessibilityMockObject::isMockObject):
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::boundingBoxForQuads):
(WebCore::AccessibilityObject::elementAccessibilityHitTest):
* accessibility/AccessibilityObject.h:
(WebCore::AccessibilityObject::isSpinButton):
(WebCore::AccessibilityObject::isSpinButtonPart):
(WebCore::AccessibilityObject::isMockObject):
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::boundingBoxRect):
(WebCore::AccessibilityRenderObject::addImageMapChildren):
(WebCore::AccessibilityRenderObject::addTextFieldChildren):
(WebCore::AccessibilityRenderObject::addChildren):
* accessibility/AccessibilityRenderObject.h:
* accessibility/AccessibilitySpinButton.cpp: Added.
(WebCore::AccessibilitySpinButton::create):
(WebCore::AccessibilitySpinButton::AccessibilitySpinButton):
(WebCore::AccessibilitySpinButton::~AccessibilitySpinButton):
(WebCore::AccessibilitySpinButton::incrementButton):
(WebCore::AccessibilitySpinButton::decrementButton):
(WebCore::AccessibilitySpinButton::elementRect):
(WebCore::AccessibilitySpinButton::addChildren):
(WebCore::AccessibilitySpinButton::step):
(WebCore::AccessibilitySpinButtonPart::AccessibilitySpinButtonPart):
(WebCore::AccessibilitySpinButtonPart::create):
(WebCore::AccessibilitySpinButtonPart::elementRect):
(WebCore::AccessibilitySpinButtonPart::press):
* accessibility/AccessibilitySpinButton.h: Added.
(WebCore::AccessibilitySpinButton::setSpinButtonElement):
(WebCore::AccessibilitySpinButton::roleValue):
(WebCore::AccessibilitySpinButton::accessibilityIsIgnored):
(WebCore::AccessibilitySpinButton::isSpinButton):
(WebCore::AccessibilitySpinButtonPart::~AccessibilitySpinButtonPart):
(WebCore::AccessibilitySpinButtonPart::isIncrementor):
(WebCore::AccessibilitySpinButtonPart::setIsIncrementor):
(WebCore::AccessibilitySpinButtonPart::roleValue):
(WebCore::AccessibilitySpinButtonPart::isSpinButtonPart):
(WebCore::AccessibilitySpinButtonPart::accessibilityIsIgnored):
(WebCore::toAccessibilitySpinButton):
(WebCore::toAccessibilitySpinButtonPart):
* accessibility/mac/WebAccessibilityObjectWrapper.mm:
(-[WebAccessibilityObjectWrapper accessibilityActionNames]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeNames]):
(-[WebAccessibilityObjectWrapper subrole]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
* html/shadow/TextControlInnerElements.cpp:
(WebCore::SpinButtonElement::step):
(WebCore::SpinButtonElement::repeatingTimerFired):
* html/shadow/TextControlInnerElements.h:

LayoutTests:

Reviewed by Darin Adler.

* platform/mac/accessibility/html5-input-number-expected.txt: Added.
* platform/mac/accessibility/html5-input-number.html: Added.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/accessibility/html5-input-number-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/accessibility/html5-input-number.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.pro
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/accessibility/AccessibilityMockObject.h
Source/WebCore/accessibility/AccessibilityObject.cpp
Source/WebCore/accessibility/AccessibilityObject.h
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/accessibility/AccessibilityRenderObject.h
Source/WebCore/accessibility/AccessibilitySpinButton.cpp [new file with mode: 0644]
Source/WebCore/accessibility/AccessibilitySpinButton.h [new file with mode: 0644]
Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapper.mm
Source/WebCore/html/shadow/TextControlInnerElements.cpp
Source/WebCore/html/shadow/TextControlInnerElements.h

index 404c444..b40a211 100644 (file)
@@ -1,3 +1,13 @@
+2011-10-17  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: buttons of number type <input> controls are not fully accessible
+        https://bugs.webkit.org/show_bug.cgi?id=70241
+
+        Reviewed by Darin Adler.
+
+        * platform/mac/accessibility/html5-input-number-expected.txt: Added.
+        * platform/mac/accessibility/html5-input-number.html: Added.
+
 2011-10-17  Dirk Pranke  <dpranke@chromium.org>
 
         More tweaking of chromium fullscreen expectations.
diff --git a/LayoutTests/platform/mac/accessibility/html5-input-number-expected.txt b/LayoutTests/platform/mac/accessibility/html5-input-number-expected.txt
new file mode 100644 (file)
index 0000000..c2bbbb8
--- /dev/null
@@ -0,0 +1,25 @@
+
+This tests that input type='number' exposes the accessibility of it's stepper correctly
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS textfield.childrenCount is 1
+PASS incrementor.role is 'AXRole: AXIncrementor'
+PASS incrementor.width > 0 is true
+PASS incrementor.height > 0 is true
+PASS incrementor.childrenCount is 2
+PASS incrementor.childAtIndex(0).role is 'AXRole: AXButton'
+PASS incrementor.childAtIndex(0).subrole is 'AXSubrole: AXIncrementArrow'
+PASS incrementor.childAtIndex(0).width > 0 is true
+PASS incrementor.childAtIndex(0).height > 0 is true
+PASS textfield.stringValue is 'AXValue: 1'
+PASS incrementor.childAtIndex(1).role is 'AXRole: AXButton'
+PASS incrementor.childAtIndex(1).subrole is 'AXSubrole: AXDecrementArrow'
+PASS incrementor.childAtIndex(1).width > 0 is true
+PASS incrementor.childAtIndex(1).height > 0 is true
+PASS textfield.stringValue is 'AXValue: 0'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/accessibility/html5-input-number.html b/LayoutTests/platform/mac/accessibility/html5-input-number.html
new file mode 100644 (file)
index 0000000..7bd3077
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../fast/js/resources/js-test-style.css">
+<script>
+var successfullyParsed = false;
+</script>
+<script src="../../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<form>
+<input id="number" type="number"><br>
+</form>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+    description("This tests that input type='number' exposes the accessibility of it's stepper correctly");
+
+    if (window.accessibilityController) {
+
+        document.getElementById("number").focus();
+        var textfield = accessibilityController.focusedElement;
+
+        // Verify that the click point is the same as the child.
+        shouldBe("textfield.childrenCount", "1");
+
+        var incrementor = textfield.childAtIndex(0);
+
+        shouldBe("incrementor.role", "'AXRole: AXIncrementor'");
+        shouldBeTrue("incrementor.width > 0");
+        shouldBeTrue("incrementor.height > 0");
+        shouldBe("incrementor.childrenCount", "2");
+
+        shouldBe("incrementor.childAtIndex(0).role", "'AXRole: AXButton'");
+        shouldBe("incrementor.childAtIndex(0).subrole", "'AXSubrole: AXIncrementArrow'");
+        shouldBeTrue("incrementor.childAtIndex(0).width > 0");
+        shouldBeTrue("incrementor.childAtIndex(0).height > 0");
+
+        // Increment.
+        incrementor.childAtIndex(0).press();
+        shouldBe("textfield.stringValue", "'AXValue: 1'");
+
+        shouldBe("incrementor.childAtIndex(1).role", "'AXRole: AXButton'");
+        shouldBe("incrementor.childAtIndex(1).subrole", "'AXSubrole: AXDecrementArrow'");
+        shouldBeTrue("incrementor.childAtIndex(1).width > 0");
+        shouldBeTrue("incrementor.childAtIndex(1).height > 0");
+
+        // Decrement.
+        incrementor.childAtIndex(1).press();
+        shouldBe("textfield.stringValue", "'AXValue: 0'");
+    }
+
+    successfullyParsed = true;
+</script>
+
+<script src="../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index 03ea122..c21c8cd 100644 (file)
@@ -410,6 +410,7 @@ SET(WebCore_SOURCES
     accessibility/AccessibilityRenderObject.cpp
     accessibility/AccessibilityScrollbar.cpp
     accessibility/AccessibilityScrollView.cpp
+    accessibility/AccessibilitySpinButton.cpp
     accessibility/AccessibilitySlider.cpp
     accessibility/AccessibilityTable.cpp
     accessibility/AccessibilityTableCell.cpp
index fe3af1d..5d600b0 100644 (file)
@@ -1,3 +1,77 @@
+2011-10-17  Chris Fleizach  <cfleizach@apple.com>
+
+        AX: buttons of number type <input> controls are not fully accessible
+        https://bugs.webkit.org/show_bug.cgi?id=70241
+
+        Expose the spin button object to the AX hierarchy. Since there is no distinct
+        render object that backs this object, a mock object needs to be created for the entire
+        spin button and the actual increment and decrement buttons inside.
+
+        Reviewed by Darin Adler.
+
+        Test: platform/mac/accessibility/html5-input-number.html
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::getOrCreate):
+        * accessibility/AccessibilityMockObject.cpp:
+        (WebCore::AccessibilityMockObject::AccessibilityMockObject):
+        * accessibility/AccessibilityMockObject.h:
+        (WebCore::AccessibilityMockObject::isMockObject):
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::boundingBoxForQuads):
+        (WebCore::AccessibilityObject::elementAccessibilityHitTest):
+        * accessibility/AccessibilityObject.h:
+        (WebCore::AccessibilityObject::isSpinButton):
+        (WebCore::AccessibilityObject::isSpinButtonPart):
+        (WebCore::AccessibilityObject::isMockObject):
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::boundingBoxRect):
+        (WebCore::AccessibilityRenderObject::addImageMapChildren):
+        (WebCore::AccessibilityRenderObject::addTextFieldChildren):
+        (WebCore::AccessibilityRenderObject::addChildren):
+        * accessibility/AccessibilityRenderObject.h:
+        * accessibility/AccessibilitySpinButton.cpp: Added.
+        (WebCore::AccessibilitySpinButton::create):
+        (WebCore::AccessibilitySpinButton::AccessibilitySpinButton):
+        (WebCore::AccessibilitySpinButton::~AccessibilitySpinButton):
+        (WebCore::AccessibilitySpinButton::incrementButton):
+        (WebCore::AccessibilitySpinButton::decrementButton):
+        (WebCore::AccessibilitySpinButton::elementRect):
+        (WebCore::AccessibilitySpinButton::addChildren):
+        (WebCore::AccessibilitySpinButton::step):
+        (WebCore::AccessibilitySpinButtonPart::AccessibilitySpinButtonPart):
+        (WebCore::AccessibilitySpinButtonPart::create):
+        (WebCore::AccessibilitySpinButtonPart::elementRect):
+        (WebCore::AccessibilitySpinButtonPart::press):
+        * accessibility/AccessibilitySpinButton.h: Added.
+        (WebCore::AccessibilitySpinButton::setSpinButtonElement):
+        (WebCore::AccessibilitySpinButton::roleValue):
+        (WebCore::AccessibilitySpinButton::accessibilityIsIgnored):
+        (WebCore::AccessibilitySpinButton::isSpinButton):
+        (WebCore::AccessibilitySpinButtonPart::~AccessibilitySpinButtonPart):
+        (WebCore::AccessibilitySpinButtonPart::isIncrementor):
+        (WebCore::AccessibilitySpinButtonPart::setIsIncrementor):
+        (WebCore::AccessibilitySpinButtonPart::roleValue):
+        (WebCore::AccessibilitySpinButtonPart::isSpinButtonPart):
+        (WebCore::AccessibilitySpinButtonPart::accessibilityIsIgnored):
+        (WebCore::toAccessibilitySpinButton):
+        (WebCore::toAccessibilitySpinButtonPart):
+        * accessibility/mac/WebAccessibilityObjectWrapper.mm:
+        (-[WebAccessibilityObjectWrapper accessibilityActionNames]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeNames]):
+        (-[WebAccessibilityObjectWrapper subrole]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
+        * html/shadow/TextControlInnerElements.cpp:
+        (WebCore::SpinButtonElement::step):
+        (WebCore::SpinButtonElement::repeatingTimerFired):
+        * html/shadow/TextControlInnerElements.h:
+
 2011-10-17  Dmitry Titov  <dimich@chromium.org>
 
         Re-landing: window.webkitNotifications uses deallocated NotificationPresenter after live Iframe transfer.
index 854dab0..d2aec07 100644 (file)
@@ -635,6 +635,8 @@ webcore_sources += \
        Source/WebCore/accessibility/AccessibilityScrollView.h \
        Source/WebCore/accessibility/AccessibilitySlider.cpp \
        Source/WebCore/accessibility/AccessibilitySlider.h \
+       Source/WebCore/accessibility/AccessibilitySpinButton.cpp \
+       Source/WebCore/accessibility/AccessibilitySpinButton.h \
        Source/WebCore/accessibility/AccessibilityTableCell.cpp \
        Source/WebCore/accessibility/AccessibilityTableCell.h \
        Source/WebCore/accessibility/AccessibilityTableColumn.cpp \
index 97952c1..b1943e4 100644 (file)
             'accessibility/AccessibilityScrollbar.h',
             'accessibility/AccessibilitySlider.cpp',
             'accessibility/AccessibilitySlider.h',
+            'accessibility/AccessibilitySpinButton.cpp',
+            'accessibility/AccessibilitySpinButton.h',
             'accessibility/AccessibilityTable.cpp',
             'accessibility/AccessibilityTable.h',
             'accessibility/AccessibilityTableCell.cpp',
index b0c4bd8..2c605da 100644 (file)
@@ -43,6 +43,7 @@ SOURCES += \
     accessibility/AccessibilityScrollbar.cpp \
     accessibility/AccessibilityScrollView.cpp \
     accessibility/AccessibilitySlider.cpp \    
+    accessibility/AccessibilitySpinButton.cpp \    
     accessibility/AccessibilityARIAGrid.cpp \    
     accessibility/AccessibilityARIAGridCell.cpp \    
     accessibility/AccessibilityARIAGridRow.cpp \    
@@ -1261,6 +1262,7 @@ HEADERS += \
     accessibility/AccessibilityScrollbar.h \
     accessibility/AccessibilityScrollView.h \
     accessibility/AccessibilitySlider.h \
+    accessibility/AccessibilitySpinButton.h \
     accessibility/AccessibilityTableCell.h \
     accessibility/AccessibilityTableColumn.h \
     accessibility/AccessibilityTable.h \
index f3cd37d..4a41d65 100755 (executable)
                                RelativePath="..\accessibility\AccessibilitySlider.h"
                                >
                        </File>
+                        <File
+                                RelativePath="..\accessibility\AccessibilitySpinButton.cpp"
+                                >
+                        </File>
+                        <File
+                                RelativePath="..\accessibility\AccessibilitySpinButton.h"
+                                >
                        <File
                                RelativePath="..\accessibility\AccessibilityTable.cpp"
                                >
index cf6b5e2..606402d 100644 (file)
                29A8124B0FBB9CA900510293 /* AXObjectCacheMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29A812470FBB9CA900510293 /* AXObjectCacheMac.mm */; };
                29ACB212143E7128006BCA5F /* AccessibilityMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 29ACB211143E7128006BCA5F /* AccessibilityMockObject.h */; };
                29ACB214143E7498006BCA5F /* AccessibilityMockObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29ACB213143E7498006BCA5F /* AccessibilityMockObject.cpp */; };
+               29D7BCF61444AF580070619C /* AccessibilitySpinButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29D7BCF51444AF580070619C /* AccessibilitySpinButton.cpp */; };
+               29D7BCFA1444AF7D0070619C /* AccessibilitySpinButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 29D7BCF91444AF7D0070619C /* AccessibilitySpinButton.h */; };
                2BE8E2C712A589EC00FAD550 /* HTMLMetaCharsetParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BE8E2C612A589EC00FAD550 /* HTMLMetaCharsetParser.h */; };
                2BE8E2C912A58A0100FAD550 /* HTMLMetaCharsetParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BE8E2C812A58A0100FAD550 /* HTMLMetaCharsetParser.cpp */; };
                2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3A0E3513A7D76100E85AF0 /* SVGParsingError.h */; settings = {ATTRIBUTES = (Private, ); }; };
                29A812470FBB9CA900510293 /* AXObjectCacheMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AXObjectCacheMac.mm; sourceTree = "<group>"; };
                29ACB211143E7128006BCA5F /* AccessibilityMockObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityMockObject.h; sourceTree = "<group>"; };
                29ACB213143E7498006BCA5F /* AccessibilityMockObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityMockObject.cpp; sourceTree = "<group>"; };
+               29D7BCF51444AF580070619C /* AccessibilitySpinButton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AccessibilitySpinButton.cpp; path = accessibility/AccessibilitySpinButton.cpp; sourceTree = SOURCE_ROOT; };
+               29D7BCF91444AF7D0070619C /* AccessibilitySpinButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySpinButton.h; sourceTree = "<group>"; };
                2BE8E2C612A589EC00FAD550 /* HTMLMetaCharsetParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLMetaCharsetParser.h; path = parser/HTMLMetaCharsetParser.h; sourceTree = "<group>"; };
                2BE8E2C812A58A0100FAD550 /* HTMLMetaCharsetParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLMetaCharsetParser.cpp; path = parser/HTMLMetaCharsetParser.cpp; sourceTree = "<group>"; };
                2D3A0E3513A7D76100E85AF0 /* SVGParsingError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGParsingError.h; sourceTree = "<group>"; };
                                29489FC512C00F0300D83F0F /* AccessibilityScrollView.h */,
                                2981CAA9131822EC00D12F2A /* AccessibilitySlider.cpp */,
                                0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */,
+                               29D7BCF51444AF580070619C /* AccessibilitySpinButton.cpp */,
+                               29D7BCF91444AF7D0070619C /* AccessibilitySpinButton.h */,
                                2981CAAA131822EC00D12F2A /* AccessibilityTable.cpp */,
                                29A8120D0FBB9C1D00510293 /* AccessibilityTable.h */,
                                2981CAAB131822EC00D12F2A /* AccessibilityTableCell.cpp */,
                                31060379143281CD00ABF4BA /* DOMWebKitCSSFilterValue.h in Headers */,
                                3106037B143281CD00ABF4BA /* DOMWebKitCSSFilterValueInternal.h in Headers */,
                                29ACB212143E7128006BCA5F /* AccessibilityMockObject.h in Headers */,
+                               29D7BCFA1444AF7D0070619C /* AccessibilitySpinButton.h in Headers */,
                                9B375EDB14478A0100F3CAE5 /* MicroDataItemList.h in Headers */,
                                49AF2D6914435D050016A784 /* DisplayRefreshMonitor.h in Headers */,
                                71CCB49D144824AC00C676D6 /* ImageBySizeCache.h in Headers */,
                                310603741432819C00ABF4BA /* JSWebKitCSSFilterValue.cpp in Sources */,
                                3106037A143281CD00ABF4BA /* DOMWebKitCSSFilterValue.mm in Sources */,
                                29ACB214143E7498006BCA5F /* AccessibilityMockObject.cpp in Sources */,
+                               29D7BCF61444AF580070619C /* AccessibilitySpinButton.cpp in Sources */,
                                0F09087F1444FDB200028917 /* ScrollbarTheme.cpp in Sources */,
                                9B375EDA14478A0100F3CAE5 /* MicroDataItemList.cpp in Sources */,
                                49AF2D6C14435D210016A784 /* DisplayRefreshMonitorMac.cpp in Sources */,
index 1c9b46a..c24bd3b 100644 (file)
@@ -45,6 +45,7 @@
 #include "AccessibilityScrollView.h"
 #include "AccessibilityScrollbar.h"
 #include "AccessibilitySlider.h"
+#include "AccessibilitySpinButton.h"
 #include "AccessibilityTable.h"
 #include "AccessibilityTableCell.h"
 #include "AccessibilityTableColumn.h"
@@ -324,6 +325,12 @@ AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole role)
     case MenuListOptionRole:
         obj = AccessibilityMenuListOption::create();
         break;
+    case SpinButtonRole:
+        obj = AccessibilitySpinButton::create();
+        break;
+    case SpinButtonPartRole:
+        obj = AccessibilitySpinButtonPart::create();
+        break;
     default:
         obj = 0;
     }
index 33f13bc..f84f965 100644 (file)
@@ -39,12 +39,15 @@ public:
     
     virtual AccessibilityObject* parentObject() const { return m_parent; }
     virtual void setParent(AccessibilityObject* parent) { m_parent = parent; };
-    
-    // Must be called when the parent object clears its children.
-    virtual void detachFromParent() { m_parent = 0; }
-    
+
 protected:
     AccessibilityObject* m_parent;
+
+private:
+    virtual bool isMockObject() const { return true; }
+
+    // Must be called when the parent object clears its children.
+    virtual void detachFromParent() { m_parent = 0; }
 }; 
     
 } // namespace WebCore 
index 8e26fcb..061edaa 100644 (file)
@@ -406,6 +406,24 @@ LayoutPoint AccessibilityObject::clickPoint()
     return LayoutPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
 }
 
+LayoutRect AccessibilityObject::boundingBoxForQuads(RenderObject* obj, const Vector<FloatQuad>& quads)
+{
+    size_t count = quads.size();
+    if (!count)
+        return LayoutRect();
+    
+    LayoutRect result;
+    for (size_t i = 0; i < count; ++i) {
+        LayoutRect r = quads[i].enclosingBoundingBox();
+        if (!r.isEmpty()) {
+            if (obj->style()->hasAppearance())
+                obj->theme()->adjustRepaintRect(obj, r);
+            result.unite(r);
+        }
+    }
+    return result;
+}
+    
 bool AccessibilityObject::press() const
 {
     Element* actionElem = actionElement();
@@ -1323,6 +1341,13 @@ AccessibilityObject* AccessibilityObject::elementAccessibilityHitTest(const Layo
         if (widget && widget->isFrameView())
             return axObjectCache()->getOrCreate(widget)->accessibilityHitTest(toPoint(point - widget->frameRect().location()));
     }
+    
+    // Check if there are any mock elements that need to be handled.
+    size_t count = m_children.size();
+    for (size_t k = 0; k < count; k++) {
+        if (m_children[k]->isMockObject() && m_children[k]->elementRect().contains(point))
+            return m_children[k]->elementAccessibilityHitTest(point);
+    }
 
     return const_cast<AccessibilityObject*>(this); 
 }
index ecccffb..c945c3f 100644 (file)
@@ -30,6 +30,7 @@
 #ifndef AccessibilityObject_h
 #define AccessibilityObject_h
 
+#include "FloatQuad.h"
 #include "LayoutTypes.h"
 #include "VisiblePosition.h"
 #include "VisibleSelection.h"
@@ -178,6 +179,8 @@ enum AccessibilityRole {
     SheetRole,
     SliderRole,
     SliderThumbRole,
+    SpinButtonRole,
+    SpinButtonPartRole,
     SplitGroupRole,
     SplitterRole,
     StaticTextRole,
@@ -369,6 +372,9 @@ public:
     virtual bool isMenuList() const { return false; }
     virtual bool isMenuListPopup() const { return false; }
     virtual bool isMenuListOption() const { return false; }
+    virtual bool isSpinButton() const { return false; }
+    virtual bool isSpinButtonPart() const { return false; }
+    virtual bool isMockObject() const { return false; }
     bool isTextControl() const { return roleValue() == TextAreaRole || roleValue() == TextFieldRole; }
     bool isARIATextControl() const;
     bool isTabList() const { return roleValue() == TabListRole; }
@@ -508,7 +514,8 @@ public:
     virtual LayoutRect elementRect() const = 0;
     virtual LayoutSize size() const { return elementRect().size(); }
     virtual LayoutPoint clickPoint();
-
+    static LayoutRect boundingBoxForQuads(RenderObject*, const Vector<FloatQuad>&);
+    
     virtual PlainTextRange selectedTextRange() const { return PlainTextRange(); }
     unsigned selectionStart() const { return selectedTextRange().start; }
     unsigned selectionEnd() const { return selectedTextRange().length; }
index 5600a22..d88dc7c 100644 (file)
@@ -32,6 +32,7 @@
 #include "AXObjectCache.h"
 #include "AccessibilityImageMapLink.h"
 #include "AccessibilityListBox.h"
+#include "AccessibilitySpinButton.h"
 #include "EventNames.h"
 #include "FloatRect.h"
 #include "Frame.h"
 #include "RenderMenuList.h"
 #include "RenderText.h"
 #include "RenderTextControl.h"
+#include "RenderTextControlSingleLine.h"
 #include "RenderTextFragment.h"
 #include "RenderTheme.h"
 #include "RenderView.h"
 #include "RenderWidget.h"
 #include "RenderedPosition.h"
 #include "Text.h"
+#include "TextControlInnerElements.h"
 #include "TextIterator.h"
 #include "htmlediting.h"
 #include "visible_units.h"
@@ -1440,19 +1443,8 @@ LayoutRect AccessibilityRenderObject::boundingBoxRect() const
         obj->absoluteQuads(quads);
     else
         obj->absoluteFocusRingQuads(quads);
-    const size_t n = quads.size();
-    if (!n)
-        return LayoutRect();
-
-    LayoutRect result;
-    for (size_t i = 0; i < n; ++i) {
-        LayoutRect r = quads[i].enclosingBoundingBox();
-        if (!r.isEmpty()) {
-            if (obj->style()->hasAppearance())
-                obj->theme()->adjustRepaintRect(obj, r);
-            result.unite(r);
-        }
-    }
+    
+    LayoutRect result = boundingBoxForQuads(obj, quads);
 
     // The size of the web area should be the content size, not the clipped size.
     if (isWebArea() && obj->frame()->view())
@@ -3465,7 +3457,31 @@ void AccessibilityRenderObject::clearChildren()
     AccessibilityObject::clearChildren();
     m_childrenDirty = false;
 }
+
+void AccessibilityRenderObject::addImageMapChildren()
+{
+    RenderBoxModelObject* cssBox = renderBoxModelObject();
+    if (!cssBox || !cssBox->isRenderImage())
+        return;
     
+    HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
+    if (!map)
+        return;
+
+    for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
+        
+        // add an <area> element for this child if it has a link
+        if (current->hasTagName(areaTag) && current->isLink()) {
+            AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
+            areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
+            areaObject->setHTMLMapElement(map);
+            areaObject->setParent(this);
+            
+            m_children.append(areaObject);
+        }
+    }
+}
+
 void AccessibilityRenderObject::updateChildrenIfNecessary()
 {
     if (needsToUpdateChildren())
@@ -3473,6 +3489,23 @@ void AccessibilityRenderObject::updateChildrenIfNecessary()
     
     AccessibilityObject::updateChildrenIfNecessary();
 }
+    
+void AccessibilityRenderObject::addTextFieldChildren()
+{
+    Node* node = this->node();
+    if (!node || !node->hasTagName(inputTag))
+        return;
+    
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
+    HTMLElement* spinButtonElement = input->innerSpinButtonElement();
+    if (!spinButtonElement || !spinButtonElement->isSpinButtonElement())
+        return;
+
+    AccessibilitySpinButton* axSpinButton = static_cast<AccessibilitySpinButton*>(axObjectCache()->getOrCreate(SpinButtonRole));
+    axSpinButton->setSpinButtonElement(static_cast<SpinButtonElement*>(spinButtonElement));
+    axSpinButton->setParent(this);
+    m_children.append(axSpinButton);
+}
 
 void AccessibilityRenderObject::addChildren()
 {
@@ -3515,25 +3548,8 @@ void AccessibilityRenderObject::addChildren()
             m_children.append(axObjectCache()->getOrCreate(widget));
     }
     
-    // for a RenderImage, add the <area> elements as individual accessibility objects
-    RenderBoxModelObject* cssBox = renderBoxModelObject();
-    if (cssBox && cssBox->isRenderImage()) {
-        HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
-        if (map) {
-            for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
-
-                // add an <area> element for this child if it has a link
-                if (current->hasTagName(areaTag) && current->isLink()) {
-                    AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
-                    areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
-                    areaObject->setHTMLMapElement(map);
-                    areaObject->setParent(this);
-
-                    m_children.append(areaObject);
-                }
-            }
-        }
-    }
+    addImageMapChildren();
+    addTextFieldChildren();
 }
         
 const AtomicString& AccessibilityRenderObject::ariaLiveRegionStatus() const
index 0d147f1..f6e2058 100644 (file)
@@ -299,6 +299,9 @@ private:
     bool renderObjectIsObservable(RenderObject*) const;
     RenderObject* renderParentObject() const;
     bool isDescendantOfElementType(const QualifiedName& tagName) const;
+
+    void addTextFieldChildren();
+    void addImageMapChildren();
     
     void ariaSelectedRows(AccessibilityChildrenVector&);
     
diff --git a/Source/WebCore/accessibility/AccessibilitySpinButton.cpp b/Source/WebCore/accessibility/AccessibilitySpinButton.cpp
new file mode 100644 (file)
index 0000000..811047b
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AccessibilitySpinButton.h"
+
+#include "AXObjectCache.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+PassRefPtr<AccessibilitySpinButton> AccessibilitySpinButton::create()
+{
+    return adoptRef(new AccessibilitySpinButton);
+}
+    
+AccessibilitySpinButton::AccessibilitySpinButton()
+    : m_spinButtonElement(0)
+{
+}
+
+AccessibilitySpinButton::~AccessibilitySpinButton()
+{
+}
+    
+AccessibilityObject* AccessibilitySpinButton::incrementButton()
+{
+    if (!m_haveChildren)
+        addChildren();
+
+    ASSERT(m_children.size() == 2);
+
+    return m_children[0].get();
+}
+   
+AccessibilityObject* AccessibilitySpinButton::decrementButton()
+{
+    if (!m_haveChildren)
+        addChildren();
+    
+    ASSERT(m_children.size() == 2);
+    
+    return m_children[1].get();    
+}
+    
+LayoutRect AccessibilitySpinButton::elementRect() const
+{
+    ASSERT(m_spinButtonElement);
+    
+    if (!m_spinButtonElement || !m_spinButtonElement->renderer())
+        return LayoutRect();
+    
+    Vector<FloatQuad> quads;
+    m_spinButtonElement->renderer()->absoluteFocusRingQuads(quads);
+
+    return boundingBoxForQuads(m_spinButtonElement->renderer(), quads);
+}
+
+void AccessibilitySpinButton::addChildren()
+{
+    m_haveChildren = true;
+    
+    AccessibilitySpinButtonPart* incrementor = static_cast<AccessibilitySpinButtonPart*>(axObjectCache()->getOrCreate(SpinButtonPartRole));
+    incrementor->setIsIncrementor(true);
+    incrementor->setParent(this);
+    m_children.append(incrementor);
+
+    AccessibilitySpinButtonPart* decrementor = static_cast<AccessibilitySpinButtonPart*>(axObjectCache()->getOrCreate(SpinButtonPartRole));
+    decrementor->setIsIncrementor(false);
+    decrementor->setParent(this);
+    m_children.append(decrementor);
+}
+    
+void AccessibilitySpinButton::step(int amount)
+{
+    ASSERT(m_spinButtonElement);
+    if (!m_spinButtonElement)
+        return;
+    
+    m_spinButtonElement->step(amount);
+}
+
+// AccessibilitySpinButtonPart 
+
+AccessibilitySpinButtonPart::AccessibilitySpinButtonPart()
+{
+}
+    
+PassRefPtr<AccessibilitySpinButtonPart> AccessibilitySpinButtonPart::create()
+{
+    return adoptRef(new AccessibilitySpinButtonPart);
+}
+
+LayoutRect AccessibilitySpinButtonPart::elementRect() const
+{
+    // FIXME: This logic should exist in the render tree or elsewhere, but there's no good 
+    // relationship that eixsts that can be queried.
+    
+    LayoutRect parentRect = parentObject()->elementRect();
+    if (m_isIncrementor)
+        parentRect.setHeight(parentRect.height() / 2);
+    else {
+        parentRect.setY(parentRect.y() + parentRect.height() / 2);        
+        parentRect.setHeight(parentRect.height() / 2);        
+    }
+        
+    return parentRect;
+}
+
+bool AccessibilitySpinButtonPart::press() const
+{
+    if (!m_parent || !m_parent->isSpinButton())
+        return false;
+    
+    AccessibilitySpinButton* spinButton = toAccessibilitySpinButton(parentObject());
+    if (m_isIncrementor)
+        spinButton->step(1);
+    else
+        spinButton->step(-1);
+    
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/accessibility/AccessibilitySpinButton.h b/Source/WebCore/accessibility/AccessibilitySpinButton.h
new file mode 100644 (file)
index 0000000..544572c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AccessibilitySpinButton_h
+#define AccessibilitySpinButton_h
+
+#include "AccessibilityMockObject.h"
+
+#include "TextControlInnerElements.h"
+
+namespace WebCore {
+    
+class AccessibilitySpinButton : public AccessibilityMockObject {
+public:
+    static PassRefPtr<AccessibilitySpinButton> create();
+    virtual ~AccessibilitySpinButton();
+    
+    void setSpinButtonElement(SpinButtonElement* spinButton) { m_spinButtonElement = spinButton; }
+    
+    AccessibilityObject* incrementButton();
+    AccessibilityObject* decrementButton();
+
+    void step(int amount);
+    
+private:
+    AccessibilitySpinButton();
+
+    virtual AccessibilityRole roleValue() const { return SpinButtonRole; }
+    virtual bool accessibilityIsIgnored() const { return false; }
+    virtual bool isSpinButton() const { return true; }
+    virtual void addChildren();
+    virtual LayoutRect elementRect() const;
+    
+    SpinButtonElement* m_spinButtonElement;
+}; 
+   
+class AccessibilitySpinButtonPart : public AccessibilityMockObject {
+public:
+    static PassRefPtr<AccessibilitySpinButtonPart> create();
+    virtual ~AccessibilitySpinButtonPart() { }
+    
+    bool isIncrementor() const { return m_isIncrementor; }
+    void setIsIncrementor(bool value) { m_isIncrementor = value; }
+    
+private:
+    AccessibilitySpinButtonPart();
+    bool m_isIncrementor : 1;
+    
+    virtual bool press() const;
+    virtual AccessibilityRole roleValue() const { return ButtonRole; }
+    virtual bool isSpinButtonPart() const { return true; }
+    virtual LayoutRect elementRect() const;
+    virtual bool accessibilityIsIgnored() const { return false; }
+};
+    
+inline AccessibilitySpinButton* toAccessibilitySpinButton(AccessibilityObject* object)
+{
+    ASSERT(!object || object->isSpinButton());
+    return static_cast<AccessibilitySpinButton*>(object);
+}
+    
+inline AccessibilitySpinButtonPart* toAccessibilitySpinButtonPart(AccessibilityObject* object)
+{
+    ASSERT(!object || object->isSpinButtonPart());
+    return static_cast<AccessibilitySpinButtonPart*>(object);
+}
+    
+} // namespace WebCore 
+
+#endif // AccessibilitySpinButton_h
index dfe7882..311a9c5 100644 (file)
@@ -37,6 +37,7 @@
 #import "AccessibilityListBox.h"
 #import "AccessibilityRenderObject.h"
 #import "AccessibilityScrollView.h"
+#import "AccessibilitySpinButton.h"
 #import "AccessibilityTable.h"
 #import "AccessibilityTableCell.h"
 #import "AccessibilityTableColumn.h"
@@ -892,7 +893,7 @@ static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosit
     static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];
 
     NSArray *actions;
-    if (m_object->actionElement()) 
+    if (m_object->actionElement() || m_object->isButton()
         actions = actionElementActions;
     else if (m_object->isMenuRelated())
         actions = menuElementActions;
@@ -984,6 +985,7 @@ static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosit
     static NSArray* outlineRowAttrs = nil;
     static NSArray* buttonAttrs = nil;
     static NSArray* scrollViewAttrs = nil;
+    static NSArray* incrementorAttrs = nil;
     NSMutableArray* tempArray;
     if (attributes == nil) {
         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
@@ -1130,6 +1132,13 @@ static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosit
         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
         [tempArray release];
     }
+    if (incrementorAttrs == nil) {
+        tempArray = [[NSMutableArray alloc] initWithArray:attributes];
+        [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
+        [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
+        incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
     if (buttonAttrs == nil) {
         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
         // Buttons should not expose AXValue.
@@ -1292,6 +1301,8 @@ static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosit
         objectAttributes = tabListAttrs;
     else if (m_object->isScrollView())
         objectAttributes = scrollViewAttrs;
+    else if (m_object->isSpinButton())
+        objectAttributes = incrementorAttrs;
     
     else if (m_object->isMenu())
         objectAttributes = menuAttrs;
@@ -1515,7 +1526,8 @@ static const AccessibilityRoleMap& createAccessibilityRoleMap()
         { ParagraphRole, NSAccessibilityGroupRole },
         { LabelRole, NSAccessibilityGroupRole },
         { DivRole, NSAccessibilityGroupRole },
-        { FormRole, NSAccessibilityGroupRole }
+        { FormRole, NSAccessibilityGroupRole },
+        { SpinButtonRole, NSAccessibilityIncrementorRole }
     };
     AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
     
@@ -1554,6 +1566,13 @@ static NSString* roleValueToNSString(AccessibilityRole value)
         }
     }
     
+    if (m_object->isSpinButtonPart()) {
+        if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
+            return NSAccessibilityIncrementArrowSubrole;
+
+        return NSAccessibilityDecrementArrowSubrole;
+    }
+    
     if (m_object->isTreeItem())
         return NSAccessibilityOutlineRowSubrole;
     
@@ -1881,6 +1900,13 @@ static NSString* roleValueToNSString(AccessibilityRole value)
         return (NSURL*)url;
     }
 
+    if (m_object->isSpinButton()) {
+        if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
+            return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
+        if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
+            return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
+    }
+    
     if ([attributeName isEqualToString: @"AXVisited"])
         return [NSNumber numberWithBool: m_object->isVisited()];
     
index f7c38e4..555bd7b 100644 (file)
@@ -344,7 +344,7 @@ void SpinButtonElement::stopRepeatingTimer()
     m_repeatingTimer.stop();
 }
 
-void SpinButtonElement::repeatingTimerFired(Timer<SpinButtonElement>*)
+void SpinButtonElement::step(int amount)
 {
     HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
     if (input->disabled() || input->isReadOnlyFormControl())
@@ -356,7 +356,12 @@ void SpinButtonElement::repeatingTimerFired(Timer<SpinButtonElement>*)
     if (m_upDownState != m_pressStartingState)
         return;
 #endif
-    input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1);
+    input->stepUpFromRenderer(amount);
+}
+    
+void SpinButtonElement::repeatingTimerFired(Timer<SpinButtonElement>*)
+{
+    step(m_upDownState == Up ? 1 : -1);
 }
 
 void SpinButtonElement::setHovered(bool flag)
index cba7d5f..c231f88 100644 (file)
@@ -100,6 +100,8 @@ public:
     UpDownState upDownState() const { return m_upDownState; }
     virtual void releaseCapture();
 
+    void step(int amount);
+    
 private:
     SpinButtonElement(Document*);