diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/accessibility/atk | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/accessibility/atk')
29 files changed, 831 insertions, 648 deletions
diff --git a/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp b/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp index 753f761e4..85e0c64d5 100644 --- a/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp +++ b/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp @@ -30,7 +30,8 @@ #include "Range.h" #include "TextIterator.h" #include "WebKitAccessibleWrapperAtk.h" -#include <wtf/gobject/GRefPtr.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/glib/GRefPtr.h> #include <wtf/text/CString.h> namespace WebCore { @@ -75,7 +76,19 @@ void AXObjectCache::attachWrapper(AccessibilityObject* obj) if (!document || document->childNeedsStyleRecalc()) return; - // Don't emit the signal for objects that we already know won't be exposed directly. + // Don't emit the signal when the actual object being added is not going to be exposed. + if (obj->accessibilityIsIgnoredByDefault()) + return; + + // Don't emit the signal if the object being added is not -- or not yet -- rendered, + // which can occur in nested iframes. In these instances we don't want to ignore the + // child. But if an assistive technology is listening, AT-SPI2 will attempt to create + // and cache the state set for the child upon emission of the signal. If the object + // has not yet been rendered, this will result in a crash. + if (!obj->renderer()) + return; + + // Don't emit the signal for objects whose parents won't be exposed directly. AccessibilityObject* coreParent = obj->parentObjectUnignored(); if (!coreParent || coreParent->accessibilityIsIgnoredByDefault()) return; @@ -119,8 +132,8 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object) // focused object and its associated list object, as per previous // calls to this function, in order to properly decide whether to // emit some signals or not. - DEFINE_STATIC_LOCAL(RefPtr<AccessibilityObject>, oldListObject, ()); - DEFINE_STATIC_LOCAL(RefPtr<AccessibilityObject>, oldFocusedObject, ()); + static NeverDestroyed<RefPtr<AccessibilityObject>> oldListObject; + static NeverDestroyed<RefPtr<AccessibilityObject>> oldFocusedObject; // Only list boxes and menu lists supported so far. if (!object || !(object->isListBox() || object->isMenuList())) @@ -128,21 +141,19 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object) // Only support HTML select elements so far (ARIA selectors not supported). Node* node = object->node(); - if (!node || !isHTMLSelectElement(node)) + if (!is<HTMLSelectElement>(node)) return; // Emit signal from the listbox's point of view first. g_signal_emit_by_name(object->wrapper(), "selection-changed"); // Find the item where the selection change was triggered from. - HTMLSelectElement* select = toHTMLSelectElement(node); - if (!select) - return; - int changedItemIndex = select->activeSelectionStartListIndex(); + HTMLSelectElement& select = downcast<HTMLSelectElement>(*node); + int changedItemIndex = select.activeSelectionStartListIndex(); AccessibilityObject* listObject = getListObject(object); if (!listObject) { - oldListObject = 0; + oldListObject.get() = nullptr; return; } @@ -154,11 +165,11 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object) // Ensure the current list object is the same than the old one so // further comparisons make sense. Otherwise, just reset // oldFocusedObject so it won't be taken into account. - if (oldListObject != listObject) - oldFocusedObject = 0; + if (oldListObject.get() != listObject) + oldFocusedObject.get() = nullptr; - AtkObject* axItem = item ? item->wrapper() : 0; - AtkObject* axOldFocusedObject = oldFocusedObject ? oldFocusedObject->wrapper() : 0; + AtkObject* axItem = item ? item->wrapper() : nullptr; + AtkObject* axOldFocusedObject = oldFocusedObject.get() ? oldFocusedObject.get()->wrapper() : nullptr; // Old focused object just lost focus, so emit the events. if (axOldFocusedObject && axItem != axOldFocusedObject) { @@ -179,8 +190,8 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object) } // Update pointers to the previously involved objects. - oldListObject = listObject; - oldFocusedObject = item; + oldListObject.get() = listObject; + oldFocusedObject.get() = item; } void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AXNotification notification) @@ -191,7 +202,7 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX switch (notification) { case AXCheckedStateChanged: - if (!coreObject->isCheckboxOrRadio()) + if (!coreObject->isCheckboxOrRadio() && !coreObject->isSwitch()) return; atk_object_notify_state_change(axObject, ATK_STATE_CHECKED, coreObject->isChecked()); break; @@ -212,7 +223,13 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX propertyValues.property_name = "accessible-value"; memset(&propertyValues.new_value, 0, sizeof(GValue)); +#if ATK_CHECK_VERSION(2,11,92) + double value; + atk_value_get_value_and_text(ATK_VALUE(axObject), &value, nullptr); + g_value_set_double(g_value_init(&propertyValues.new_value, G_TYPE_DOUBLE), value); +#else atk_value_get_current_value(ATK_VALUE(axObject), &propertyValues.new_value); +#endif g_signal_emit_by_name(ATK_OBJECT(axObject), "property-change::accessible-value", &propertyValues, NULL); } @@ -232,7 +249,7 @@ void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* obje if (!object || text.isEmpty()) return; - AccessibilityObject* parentObject = object->parentObjectUnignored(); + AccessibilityObject* parentObject = object->isNonNativeTextControl() ? object : object->parentObjectUnignored(); if (!parentObject) return; @@ -251,12 +268,15 @@ void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* obje // Select the right signal to be emitted CString detail; switch (textChange) { - case AXObjectCache::AXTextInserted: + case AXTextInserted: detail = "text-insert"; break; - case AXObjectCache::AXTextDeleted: + case AXTextDeleted: detail = "text-remove"; break; + case AXTextAttributesChanged: + detail = "text-attributes-changed"; + break; } String textToEmit = text; diff --git a/Source/WebCore/accessibility/atk/AccessibilityObjectAtk.cpp b/Source/WebCore/accessibility/atk/AccessibilityObjectAtk.cpp index 51e1b787a..238248430 100644 --- a/Source/WebCore/accessibility/atk/AccessibilityObjectAtk.cpp +++ b/Source/WebCore/accessibility/atk/AccessibilityObjectAtk.cpp @@ -21,9 +21,13 @@ #include "config.h" #include "AccessibilityObject.h" -#include "HTMLNames.h" -#include "RenderObject.h" +#include "HTMLSpanElement.h" +#include "RenderBlock.h" +#include "RenderInline.h" +#include "RenderIterator.h" +#include "RenderTableCell.h" #include "RenderText.h" +#include "TextControlInnerElements.h" #include <glib-object.h> #if HAVE(ACCESSIBILITY) @@ -41,10 +45,11 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO if (!parent) return DefaultBehavior; - AccessibilityRole role = roleValue(); - if (role == HorizontalRuleRole) - return IncludeObject; + // If the author has provided a role, platform-specific inclusion likely doesn't apply. + if (ariaRoleAttribute() != UnknownRole) + return DefaultBehavior; + AccessibilityRole role = roleValue(); // We expose the slider as a whole but not its value indicator. if (role == SliderThumbRole) return IgnoreObject; @@ -59,12 +64,13 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO return IgnoreObject; // Include all tables, even layout tables. The AT can decide what to do with each. - if (role == CellRole || role == TableRole) + if (role == CellRole || role == TableRole || role == ColumnHeaderRole || role == RowHeaderRole) return IncludeObject; // The object containing the text should implement AtkText itself. + // However, WebCore also maps ARIA's "text" role to the StaticTextRole. if (role == StaticTextRole) - return IgnoreObject; + return ariaRoleAttribute() != UnknownRole ? DefaultBehavior : IgnoreObject; // Include all list items, regardless they have or not inline children if (role == ListItemRole) @@ -79,52 +85,72 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO if (role == UnknownRole) return IgnoreObject; + if (role == InlineRole) + return IncludeObject; + // Lines past this point only make sense for AccessibilityRenderObjects. RenderObject* renderObject = renderer(); if (!renderObject) return DefaultBehavior; + // We always want to include paragraphs that have rendered content. + // WebCore Accessibility does so unless there is a RenderBlock child. + if (role == ParagraphRole) { + auto child = childrenOfType<RenderBlock>(downcast<RenderElement>(*renderObject)).first(); + return child ? IncludeObject : DefaultBehavior; + } + + // We always want to include table cells (layout and CSS) that have rendered text content. + if (is<RenderTableCell>(renderObject)) { + for (const auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*renderObject))) { + if (is<RenderInline>(child) || is<RenderText>(child) || is<HTMLSpanElement>(child.node())) + return IncludeObject; + } + return DefaultBehavior; + } + + if (renderObject->isAnonymousBlock()) { + // The text displayed by an ARIA menu item is exposed through the accessible name. + if (parent->isMenuItem()) + return IgnoreObject; + + // The text displayed in headings is typically exposed in the heading itself. + if (parent->isHeading()) + return IgnoreObject; + + // The text displayed in list items is typically exposed in the list item itself. + if (parent->isListItem()) + return IgnoreObject; + + // The text displayed in links is typically exposed in the link itself. + if (parent->isLink()) + return IgnoreObject; + + // FIXME: This next one needs some further consideration. But paragraphs are not + // typically huge (like divs). And ignoring anonymous block children of paragraphs + // will preserve existing behavior. + if (parent->roleValue() == ParagraphRole) + return IgnoreObject; + + return DefaultBehavior; + } + + Node* node = renderObject->node(); + if (!node) + return DefaultBehavior; + // We don't want <span> elements to show up in the accessibility hierarchy unless // we have good reasons for that (e.g. focusable or visible because of containing // a meaningful accessible name, maybe set through ARIA), so we can use // atk_component_grab_focus() to set the focus to it. - Node* node = renderObject->node(); - if (node && node->hasTagName(HTMLNames::spanTag) && !canSetFocusAttribute() && !hasAttributesRequiredForInclusion()) + if (is<HTMLSpanElement>(node) && !canSetFocusAttribute() && !hasAttributesRequiredForInclusion() && !supportsARIAAttributes()) return IgnoreObject; - // Given a paragraph or div containing a non-nested anonymous block, WebCore - // ignores the paragraph or div and includes the block. We want the opposite: - // ATs are expecting accessible objects associated with textual elements. They - // usually have no need for the anonymous block. And when the wrong objects - // get included or ignored, needed accessibility signals do not get emitted. - if (role == ParagraphRole || role == DivRole) { - // Don't call textUnderElement() here, because it's slow and it can - // crash when called while we're in the middle of a subtree being deleted. - if (!renderObject->firstChildSlow()) - return DefaultBehavior; - - if (!parent->renderer() || parent->renderer()->isAnonymousBlock()) - return DefaultBehavior; - - for (RenderObject* r = renderObject->firstChildSlow(); r; r = r->nextSibling()) { - if (r->isAnonymousBlock()) - return IncludeObject; - } - } - - // Block spans result in objects of ATK_ROLE_PANEL which are almost always unwanted. - // However, if we ignore block spans whose parent is the body, the child controls - // will become immediate children of the ATK_ROLE_DOCUMENT_FRAME and any text will - // become text within the document frame itself. This ultimately may be what we want - // and would largely be consistent with what we see from Gecko. However, ignoring - // spans whose parent is the body changes the current behavior we see from WebCore. - // Until we have sufficient time to properly analyze these cases, we will defer to - // WebCore. We only check that the parent is not aria because we do not expect - // anonymous blocks which are aria-related to themselves have an aria role, nor - // have we encountered instances where the parent of an anonymous block also lacked - // an aria role but the grandparent had one. - if (renderObject && renderObject->isAnonymousBlock() && !parent->renderer()->isBody() - && parent->ariaRoleAttribute() == UnknownRole) + // If we include TextControlInnerTextElement children, changes to those children + // will result in focus and text notifications that suggest the user is no longer + // in the control. This can be especially problematic for screen reader users with + // key echo enabled when typing in a password input. + if (is<TextControlInnerTextElement>(node)) return IgnoreObject; return DefaultBehavior; @@ -157,7 +183,7 @@ bool AccessibilityObject::allowsTextRanges() const // Check roles as the last fallback mechanism. AccessibilityRole role = roleValue(); - return role == ParagraphRole || role == LabelRole || role == DivRole || role == FormRole; + return role == ParagraphRole || role == LabelRole || role == DivRole || role == FormRole || role == PreRole; } unsigned AccessibilityObject::getLengthForTextRange() const @@ -169,9 +195,9 @@ unsigned AccessibilityObject::getLengthForTextRange() const // Gtk ATs need this for all text objects; not just text controls. Node* node = this->node(); - RenderObject* renderer = node ? node->renderer() : 0; - if (renderer && renderer->isText()) - textLength = toRenderText(*renderer).textLength(); + RenderObject* renderer = node ? node->renderer() : nullptr; + if (is<RenderText>(renderer)) + textLength = downcast<RenderText>(*renderer).textLength(); // Get the text length from the elements under the // accessibility object if the value is still zero. diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.cpp index 0e4a0c8ed..9df03efa9 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.cpp @@ -231,10 +231,10 @@ static gint getRangeLengthForObject(AccessibilityObject* obj, Range* range) return baseLength; RenderObject* renderer = markerObj->renderer(); - if (!renderer || !renderer->isListMarker()) + if (!is<RenderListMarker>(renderer)) return baseLength; - RenderListMarker& marker = toRenderListMarker(*renderer); + auto& marker = downcast<RenderListMarker>(*renderer); return baseLength + marker.text().length() + marker.suffix().length(); } @@ -385,7 +385,7 @@ static void webkitAccessibleHyperlinkClassInit(AtkHyperlinkClass* klass) static void webkitAccessibleHyperlinkInit(AtkHyperlink* link) { WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv = WEBKIT_ACCESSIBLE_HYPERLINK_GET_PRIVATE(link); - WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl = 0; + WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl = nullptr; } GType webkitAccessibleHyperlinkGetType() diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.h b/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.h index 59ca73cea..0533156e7 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.h @@ -17,8 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleHyperlink_h -#define WebKitAccessibleHyperlink_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -60,6 +59,4 @@ WebCore::AccessibilityObject* webkitAccessibleHyperlinkGetAccessibilityObject(We G_END_DECLS -#endif // WebKitAccessibleHyperlink_h - -#endif +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceAction.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceAction.h index a0de63fd7..5cd75287b 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceAction.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceAction.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceAction_h -#define WebKitAccessibleInterfaceAction_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,6 +27,4 @@ void webkitAccessibleActionInterfaceInit(AtkActionIface*); -#endif - -#endif // WebKitAccessibleInterfaceAction_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.cpp index b93d8c39d..e86f23098 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.cpp @@ -85,7 +85,7 @@ static void webkitAccessibleComponentGetExtents(AtkComponent* component, gint* x g_return_if_fail(ATK_IS_COMPONENT(component)); returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(component)); - IntRect rect = pixelSnappedIntRect(core(component)->elementRect()); + IntRect rect = snappedIntRect(core(component)->elementRect()); contentsRelativeToAtkCoordinateType(core(component), coordType, rect, x, y, width, height); } diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.h index 4ccfd97a4..209d51e7e 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceComponent.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceComponent_h -#define WebKitAccessibleInterfaceComponent_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,6 +27,4 @@ void webkitAccessibleComponentInterfaceInit(AtkComponentIface*); -#endif - -#endif // WebKitAccessibleInterfaceComponent_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.cpp index 5a52f8130..6752d12d3 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.cpp @@ -89,7 +89,7 @@ static AtkAttributeSet* webkitAccessibleDocumentGetAttributes(AtkDocument* docum g_return_val_if_fail(ATK_IS_DOCUMENT(document), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(document), 0); - AtkAttributeSet* attributeSet = 0; + AtkAttributeSet* attributeSet = nullptr; const gchar* attributes[] = { "DocType", "Encoding", "URI" }; for (unsigned i = 0; i < G_N_ELEMENTS(attributes); i++) { diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.h index 5ee946962..6fab32ada 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceDocument.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceDocument_h -#define WebKitAccessibleInterfaceDocument_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleDocumentInterfaceInit(AtkDocumentIface*); -#endif -#endif // WebKitAccessibleInterfaceDocument_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceEditableText.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceEditableText.h index da7669130..6414e2d88 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceEditableText.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceEditableText.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceEditableText_h -#define WebKitAccessibleInterfaceEditableText_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleEditableTextInterfaceInit(AtkEditableTextIface*); -#endif -#endif // WebKitAccessibleInterfaceEditableText_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHyperlinkImpl.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHyperlinkImpl.h index 56a8c67ac..c9eebac5b 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHyperlinkImpl.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHyperlinkImpl.h @@ -17,8 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceHyperlinkImpl_h -#define WebKitAccessibleInterfaceHyperlinkImpl_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -26,5 +25,4 @@ void webkitAccessibleHyperlinkImplInterfaceInit(AtkHyperlinkImplIface*); -#endif -#endif // WebKitAccessibleInterfaceHyperlinkImpl_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.cpp index 75c045c01..db60218df 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.cpp @@ -70,12 +70,9 @@ static gint webkitAccessibleHypertextGetNLinks(AtkHypertext* hypertext) returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(hypertext), 0); const AccessibilityObject::AccessibilityChildrenVector& children = core(hypertext)->children(); - if (!children.size()) - return 0; - gint linksFound = 0; - for (size_t i = 0; i < children.size(); i++) { - AccessibilityObject* coreChild = children.at(i).get(); + for (const auto& child : children) { + AccessibilityObject* coreChild = child.get(); if (!coreChild->accessibilityIsIgnored()) { AtkObject* axObject = coreChild->wrapper(); if (axObject && ATK_IS_HYPERLINK_IMPL(axObject)) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.h index 7a3a0892a..da163af23 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceHypertext.h @@ -17,8 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceHypertext_h -#define WebKitAccessibleInterfaceHypertext_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -26,6 +25,4 @@ void webkitAccessibleHypertextInterfaceInit(AtkHypertextIface*); -#endif - -#endif // WebKitAccessibleInterfaceHypertext_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.cpp index bab75995a..843969b42 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.cpp @@ -54,7 +54,7 @@ static void webkitAccessibleImageGetImagePosition(AtkImage* image, gint* x, gint g_return_if_fail(ATK_IMAGE(image)); returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(image)); - IntRect rect = pixelSnappedIntRect(core(image)->elementRect()); + IntRect rect = snappedIntRect(core(image)->elementRect()); contentsRelativeToAtkCoordinateType(core(image), coordType, rect, x, y); } @@ -71,7 +71,7 @@ static void webkitAccessibleImageGetImageSize(AtkImage* image, gint* width, gint g_return_if_fail(ATK_IMAGE(image)); returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(image)); - IntSize size = core(image)->pixelSnappedSize(); + IntSize size = snappedIntRect(core(image)->elementRect()).size(); if (width) *width = size.width(); diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.h index 45be65541..4f31640c9 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceImage.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceImage_h -#define WebKitAccessibleInterfaceImage_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleImageInterfaceInit(AtkImageIface*); -#endif -#endif // WebKitAccessibleInterfaceImage_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.cpp index cb7a3ccff..ec7f8caa5 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.cpp @@ -45,7 +45,7 @@ using namespace WebCore; static AccessibilityObject* core(AtkSelection* selection) { if (!WEBKIT_IS_ACCESSIBLE(selection)) - return 0; + return nullptr; return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(selection)); } @@ -56,7 +56,7 @@ static AccessibilityObject* listObjectForSelection(AtkSelection* selection) // Only list boxes and menu lists supported so far. if (!coreSelection->isListBox() && !coreSelection->isMenuList()) - return 0; + return nullptr; // For list boxes the list object is just itself. if (coreSelection->isListBox()) @@ -67,11 +67,11 @@ static AccessibilityObject* listObjectForSelection(AtkSelection* selection) // of items with role MenuListOptionRole. const AccessibilityObject::AccessibilityChildrenVector& children = coreSelection->children(); if (!children.size()) - return 0; + return nullptr; AccessibilityObject* listObject = children.at(0).get(); if (!listObject->isMenuListPopup()) - return 0; + return nullptr; return listObject; } @@ -80,50 +80,37 @@ static AccessibilityObject* optionFromList(AtkSelection* selection, gint index) { AccessibilityObject* coreSelection = core(selection); if (!coreSelection || index < 0) - return 0; + return nullptr; // Need to select the proper list object depending on the type. AccessibilityObject* listObject = listObjectForSelection(selection); if (!listObject) - return 0; + return nullptr; const AccessibilityObject::AccessibilityChildrenVector& options = listObject->children(); if (index < static_cast<gint>(options.size())) return options.at(index).get(); - return 0; + return nullptr; } static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint index) { - // i is the ith selection as opposed to the ith child. - AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isAccessibilityRenderObject() || index < 0) - return 0; - - AccessibilityObject::AccessibilityChildrenVector selectedItems; - if (coreSelection->isListBox()) - coreSelection->selectedChildren(selectedItems); - else if (coreSelection->isMenuList()) { - RenderObject* renderer = coreSelection->renderer(); - if (!renderer) - return 0; - - HTMLSelectElement* selectNode = toHTMLSelectElement(renderer->node()); - int selectedIndex = selectNode->selectedIndex(); - const Vector<HTMLElement*> listItems = selectNode->listItems(); - - if (selectedIndex < 0 || selectedIndex >= static_cast<int>(listItems.size())) - return 0; - - return optionFromList(selection, selectedIndex); - } - - if (index < static_cast<gint>(selectedItems.size())) - return selectedItems.at(index).get(); + return nullptr; + + // This method provides the functionality expected by atk_selection_ref_selection(). + // According to the ATK documentation for this method, the index is "a gint specifying + // the index in the selection set. (e.g. the ith selection as opposed to the ith child)." + // There is different API, namely atk_object_ref_accessible_child(), when the ith child + // from the set of all children is sought. + AccessibilityObject::AccessibilityChildrenVector options; + coreSelection->selectedChildren(options); + if (index < static_cast<gint>(options.size())) + return options.at(index).get(); - return 0; + return nullptr; } static gboolean webkitAccessibleSelectionAddSelection(AtkSelection* selection, gint index) @@ -154,20 +141,20 @@ static gboolean webkitAccessibleSelectionClearSelection(AtkSelection* selection) return FALSE; AccessibilityObject::AccessibilityChildrenVector selectedItems; - if (coreSelection->isListBox() || coreSelection->isMenuList()) { + if (is<AccessibilityListBox>(*coreSelection)) { // Set the list of selected items to an empty list; then verify that it worked. - AccessibilityListBox* listBox = toAccessibilityListBox(coreSelection); - listBox->setSelectedChildren(selectedItems); - listBox->selectedChildren(selectedItems); - return !selectedItems.size(); + auto& listBox = downcast<AccessibilityListBox>(*coreSelection); + listBox.setSelectedChildren(selectedItems); + listBox.selectedChildren(selectedItems); + return selectedItems.isEmpty(); } return FALSE; } static AtkObject* webkitAccessibleSelectionRefSelection(AtkSelection* selection, gint index) { - g_return_val_if_fail(ATK_SELECTION(selection), 0); - returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), 0); + g_return_val_if_fail(ATK_SELECTION(selection), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), nullptr); AccessibilityObject* option = optionFromSelection(selection, index); if (option) { @@ -176,7 +163,7 @@ static AtkObject* webkitAccessibleSelectionRefSelection(AtkSelection* selection, return child; } - return 0; + return nullptr; } static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection) @@ -188,22 +175,18 @@ static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection) if (!coreSelection || !coreSelection->isAccessibilityRenderObject()) return 0; - if (coreSelection->isListBox()) { - AccessibilityObject::AccessibilityChildrenVector selectedItems; - coreSelection->selectedChildren(selectedItems); - return static_cast<gint>(selectedItems.size()); - } - if (coreSelection->isMenuList()) { RenderObject* renderer = coreSelection->renderer(); if (!renderer) return 0; - int selectedIndex = toHTMLSelectElement(renderer->node())->selectedIndex(); - return selectedIndex >= 0 && selectedIndex < static_cast<int>(toHTMLSelectElement(renderer->node())->listItems().size()); + int selectedIndex = downcast<HTMLSelectElement>(renderer->node())->selectedIndex(); + return selectedIndex >= 0 && selectedIndex < static_cast<int>(downcast<HTMLSelectElement>(renderer->node())->listItems().size()); } - return 0; + AccessibilityObject::AccessibilityChildrenVector selectedItems; + coreSelection->selectedChildren(selectedItems); + return static_cast<gint>(selectedItems.size()); } static gboolean webkitAccessibleSelectionIsChildSelected(AtkSelection* selection, gint index) @@ -231,7 +214,6 @@ static gboolean webkitAccessibleSelectionRemoveSelection(AtkSelection* selection if (!coreSelection) return FALSE; - // TODO: This is only getting called if i == 0. What is preventing the rest? AccessibilityObject* option = optionFromSelection(selection, index); if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) { option->setSelected(false); @@ -250,12 +232,12 @@ static gboolean webkitAccessibleSelectionSelectAllSelection(AtkSelection* select if (!coreSelection || !coreSelection->isMultiSelectable()) return FALSE; - if (coreSelection->isListBox()) { + if (is<AccessibilityListBox>(*coreSelection)) { const AccessibilityObject::AccessibilityChildrenVector& children = coreSelection->children(); - AccessibilityListBox* listBox = toAccessibilityListBox(coreSelection); - listBox->setSelectedChildren(children); + AccessibilityListBox& listBox = downcast<AccessibilityListBox>(*coreSelection); + listBox.setSelectedChildren(children); AccessibilityObject::AccessibilityChildrenVector selectedItems; - listBox->selectedChildren(selectedItems); + listBox.selectedChildren(selectedItems); return selectedItems.size() == children.size(); } diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.h index 6500029d0..e0f50aa82 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceSelection.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceSelection_h -#define WebKitAccessibleInterfaceSelection_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleSelectionInterfaceInit(AtkSelectionIface*); -#endif -#endif // WebKitAccessibleInterfaceSelection_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.cpp index f6ed19c0a..a03443afc 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.cpp @@ -37,7 +37,6 @@ #include "AccessibilityObject.h" #include "AccessibilityTable.h" #include "AccessibilityTableCell.h" -#include "HTMLSelectElement.h" #include "HTMLTableCaptionElement.h" #include "HTMLTableElement.h" #include "RenderElement.h" @@ -50,7 +49,7 @@ using namespace WebCore; static AccessibilityObject* core(AtkTable* table) { if (!WEBKIT_IS_ACCESSIBLE(table)) - return 0; + return nullptr; return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(table)); } @@ -58,9 +57,9 @@ static AccessibilityObject* core(AtkTable* table) static AccessibilityTableCell* cell(AtkTable* table, guint row, guint column) { AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) - return toAccessibilityTable(accTable)->cellForColumnAndRow(column, row); - return 0; + if (is<AccessibilityTable>(*accTable)) + return downcast<AccessibilityTable>(*accTable).cellForColumnAndRow(column, row); + return nullptr; } static gint cellIndex(AccessibilityTableCell* axCell, AccessibilityTable* axTable) @@ -79,15 +78,13 @@ static gint cellIndex(AccessibilityTableCell* axCell, AccessibilityTable* axTabl static AccessibilityTableCell* cellAtIndex(AtkTable* table, gint index) { AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) { + if (is<AccessibilityTable>(*accTable)) { AccessibilityObject::AccessibilityChildrenVector allCells; - toAccessibilityTable(accTable)->cells(allCells); - if (0 <= index && static_cast<unsigned>(index) < allCells.size()) { - AccessibilityObject* accCell = allCells.at(index).get(); - return toAccessibilityTableCell(accCell); - } + downcast<AccessibilityTable>(*accTable).cells(allCells); + if (0 <= index && static_cast<unsigned>(index) < allCells.size()) + return downcast<AccessibilityTableCell>(allCells[index].get()); } - return 0; + return nullptr; } static AtkObject* webkitAccessibleTableRefAt(AtkTable* table, gint row, gint column) @@ -114,7 +111,7 @@ static gint webkitAccessibleTableGetIndexAt(AtkTable* table, gint row, gint colu returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), -1); AccessibilityTableCell* axCell = cell(table, row, column); - AccessibilityTable* axTable = toAccessibilityTable(core(table)); + AccessibilityTable* axTable = downcast<AccessibilityTable>(core(table)); return cellIndex(axCell, axTable); } @@ -152,8 +149,8 @@ static gint webkitAccessibleTableGetNColumns(AtkTable* table) returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) - return toAccessibilityTable(accTable)->columnCount(); + if (is<AccessibilityTable>(*accTable)) + return downcast<AccessibilityTable>(*accTable).columnCount(); return 0; } @@ -163,8 +160,8 @@ static gint webkitAccessibleTableGetNRows(AtkTable* table) returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) - return toAccessibilityTable(accTable)->rowCount(); + if (is<AccessibilityTable>(*accTable)) + return downcast<AccessibilityTable>(*accTable).rowCount(); return 0; } @@ -202,18 +199,18 @@ static AtkObject* webkitAccessibleTableGetColumnHeader(AtkTable* table, gint col returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) { + if (is<AccessibilityTable>(*accTable)) { AccessibilityObject::AccessibilityChildrenVector columnHeaders; - toAccessibilityTable(accTable)->columnHeaders(columnHeaders); + downcast<AccessibilityTable>(*accTable).columnHeaders(columnHeaders); for (const auto& columnHeader : columnHeaders) { std::pair<unsigned, unsigned> columnRange; - toAccessibilityTableCell(columnHeader.get())->columnIndexRange(columnRange); + downcast<AccessibilityTableCell>(*columnHeader).columnIndexRange(columnRange); if (columnRange.first <= static_cast<unsigned>(column) && static_cast<unsigned>(column) < columnRange.first + columnRange.second) return columnHeader->wrapper(); } } - return 0; + return nullptr; } static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row) @@ -222,35 +219,35 @@ static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row) returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); AccessibilityObject* accTable = core(table); - if (accTable->isAccessibilityRenderObject()) { + if (is<AccessibilityTable>(*accTable)) { AccessibilityObject::AccessibilityChildrenVector rowHeaders; - toAccessibilityTable(accTable)->rowHeaders(rowHeaders); + downcast<AccessibilityTable>(*accTable).rowHeaders(rowHeaders); for (const auto& rowHeader : rowHeaders) { std::pair<unsigned, unsigned> rowRange; - toAccessibilityTableCell(rowHeader.get())->rowIndexRange(rowRange); + downcast<AccessibilityTableCell>(*rowHeader).rowIndexRange(rowRange); if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second) return rowHeader->wrapper(); } } - return 0; + return nullptr; } static AtkObject* webkitAccessibleTableGetCaption(AtkTable* table) { - g_return_val_if_fail(ATK_TABLE(table), 0); - returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); + g_return_val_if_fail(ATK_TABLE(table), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), nullptr); AccessibilityObject* accTable = core(table); if (accTable->isAccessibilityRenderObject()) { Node* node = accTable->node(); - if (node && isHTMLTableElement(node)) { - HTMLTableCaptionElement* caption = toHTMLTableElement(node)->caption(); + if (is<HTMLTableElement>(node)) { + HTMLTableCaptionElement* caption = downcast<HTMLTableElement>(*node).caption(); if (caption) return AccessibilityObject::firstAccessibleObjectFromNode(caption->renderer()->element())->wrapper(); } } - return 0; + return nullptr; } static const gchar* webkitAccessibleTableGetColumnDescription(AtkTable* table, gint column) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.h index 5bddf39c2..eacc4dfea 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTable.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceTable_h -#define WebKitAccessibleInterfaceTable_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleTableInterfaceInit(AtkTableIface*); -#endif -#endif // WebKitAccessibleInterfaceTable_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.cpp new file mode 100644 index 000000000..3d1e96211 --- /dev/null +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitAccessibleInterfaceTableCell.h" + +#if HAVE(ACCESSIBILITY) +#if ATK_CHECK_VERSION(2,11,90) +#include "AccessibilityObject.h" +#include "AccessibilityTable.h" +#include "AccessibilityTableCell.h" +#include "WebKitAccessibleUtil.h" +#include "WebKitAccessibleWrapperAtk.h" + +using namespace WebCore; + +static GPtrArray* convertToGPtrArray(const AccessibilityObject::AccessibilityChildrenVector& children) +{ + GPtrArray* array = g_ptr_array_new(); + for (const auto& child : children) { + if (AtkObject* atkObject = child->wrapper()) + g_ptr_array_add(array, atkObject); + } + return array; +} + +static AccessibilityObject* core(AtkTableCell* cell) +{ + if (!WEBKIT_IS_ACCESSIBLE(cell)) + return nullptr; + + return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(cell)); +} + +GPtrArray* webkitAccessibleTableCellGetColumnHeaderCells(AtkTableCell* cell) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr); + + AccessibilityObject* axObject = core(cell); + if (!is<AccessibilityTableCell>(axObject)) + return nullptr; + + AccessibilityObject::AccessibilityChildrenVector columnHeaders; + downcast<AccessibilityTableCell>(*axObject).columnHeaders(columnHeaders); + + return convertToGPtrArray(columnHeaders); +} + +GPtrArray* webkitAccessibleTableCellGetRowHeaderCells(AtkTableCell* cell) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr); + + AccessibilityObject* axObject = core(cell); + if (!is<AccessibilityTableCell>(axObject)) + return nullptr; + + AccessibilityObject::AccessibilityChildrenVector rowHeaders; + downcast<AccessibilityTableCell>(*axObject).rowHeaders(rowHeaders); + + return convertToGPtrArray(rowHeaders); +} + +gint webkitAccessibleTableCellGetColumnSpan(AtkTableCell* cell) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), 0); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), 0); + + AccessibilityObject* axObject = core(cell); + if (!is<AccessibilityTableCell>(axObject)) + return 0; + + std::pair<unsigned, unsigned> columnRange; + downcast<AccessibilityTableCell>(*axObject).columnIndexRange(columnRange); + + return columnRange.second; +} + +gint webkitAccessibleTableCellGetRowSpan(AtkTableCell* cell) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), 0); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), 0); + + AccessibilityObject* axObject = core(cell); + if (!is<AccessibilityTableCell>(axObject)) + return 0; + + std::pair<unsigned, unsigned> rowRange; + downcast<AccessibilityTableCell>(*axObject).rowIndexRange(rowRange); + + return rowRange.second; +} + +gboolean webkitAccessibleTableCellGetPosition(AtkTableCell* cell, gint* row, gint* column) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), false); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), false); + + AccessibilityObject* axObject = core(cell); + if (!is<AccessibilityTableCell>(axObject)) + return false; + + std::pair<unsigned, unsigned> columnRowRange; + if (row) { + downcast<AccessibilityTableCell>(*axObject).rowIndexRange(columnRowRange); + *row = columnRowRange.first; + } + if (column) { + downcast<AccessibilityTableCell>(*axObject).columnIndexRange(columnRowRange); + *column = columnRowRange.first; + } + + return true; +} + +AtkObject* webkitAccessibleTableCellGetTable(AtkTableCell* cell) +{ + g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr); + + AccessibilityObject* axObject = core(cell); + if (!axObject || !axObject->isTableCell()) + return nullptr; + + AtkObject* table = atk_object_get_parent(axObject->wrapper()); + if (!table || !ATK_IS_TABLE(table)) + return nullptr; + + return ATK_OBJECT(g_object_ref(table)); +} + +void webkitAccessibleTableCellInterfaceInit(AtkTableCellIface* iface) +{ + iface->get_column_header_cells = webkitAccessibleTableCellGetColumnHeaderCells; + iface->get_row_header_cells = webkitAccessibleTableCellGetRowHeaderCells; + iface->get_column_span = webkitAccessibleTableCellGetColumnSpan; + iface->get_row_span = webkitAccessibleTableCellGetRowSpan; + iface->get_position = webkitAccessibleTableCellGetPosition; + iface->get_table = webkitAccessibleTableCellGetTable; +} + +#endif // ATK_CHECK_VERSION(2,11,90) +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.h new file mode 100644 index 000000000..d2f58c6fb --- /dev/null +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceTableCell.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2009 Jan Alonzo + * Copyright (C) 2009, 2010, 2011, 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#if HAVE(ACCESSIBILITY) + +#include <atk/atk.h> + +#if ATK_CHECK_VERSION(2,11,90) +void webkitAccessibleTableCellInterfaceInit(AtkTableCellIface*); +#endif + +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp index 8422d7045..5edcc98f3 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp @@ -36,7 +36,7 @@ #include "AccessibilityObject.h" #include "Document.h" -#include "Font.h" +#include "FontCascade.h" #include "FrameView.h" #include "HTMLParserIdioms.h" #include "HostWindow.h" @@ -51,7 +51,7 @@ #include "WebKitAccessibleUtil.h" #include "WebKitAccessibleWrapperAtk.h" #include "htmlediting.h" -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> using namespace WebCore; @@ -84,9 +84,9 @@ static AtkAttributeSet* getAttributeSetForAccessibilityObject(const Accessibilit return 0; RenderObject* renderer = object->renderer(); - RenderStyle* style = &renderer->style(); + auto* style = &renderer->style(); - AtkAttributeSet* result = 0; + AtkAttributeSet* result = nullptr; GUniquePtr<gchar> buffer(g_strdup_printf("%i", style->fontSize())); result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_SIZE), buffer.get()); @@ -125,19 +125,19 @@ static AtkAttributeSet* getAttributeSetForAccessibilityObject(const Accessibilit } if (!style->textIndent().isUndefined()) { - int indentation = valueForLength(style->textIndent(), object->size().width(), &renderer->view()); + int indentation = valueForLength(style->textIndent(), object->size().width()); buffer.reset(g_strdup_printf("%i", indentation)); result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_INDENT), buffer.get()); } - String fontFamilyName = style->font().firstFamily(); + String fontFamilyName = style->fontCascade().firstFamily(); if (fontFamilyName.left(8) == "-webkit-") fontFamilyName = fontFamilyName.substring(8); result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_FAMILY_NAME), fontFamilyName.utf8().data()); int fontWeight = -1; - switch (style->font().weight()) { + switch (style->fontCascade().weight()) { case FontWeight100: fontWeight = 100; break; @@ -192,19 +192,19 @@ static AtkAttributeSet* getAttributeSetForAccessibilityObject(const Accessibilit result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_UNDERLINE), (style->textDecoration() & TextDecorationUnderline) ? "single" : "none"); - result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_STYLE), style->font().italic() ? "italic" : "normal"); + result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_STYLE), style->fontCascade().italic() ? "italic" : "normal"); result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_STRIKETHROUGH), (style->textDecoration() & TextDecorationLineThrough) ? "true" : "false"); result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_INVISIBLE), (style->visibility() == HIDDEN) ? "true" : "false"); - result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_EDITABLE), object->isReadOnly() ? "false" : "true"); + result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_EDITABLE), object->canSetValueAttribute() ? "true" : "false"); String language = object->language(); if (!language.isEmpty()) result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_LANGUAGE), language.utf8().data()); - String invalidStatus = object->invalidStatus().string(); + String invalidStatus = object->invalidStatus(); if (invalidStatus != "false") { // Register the custom attribute for 'aria-invalid' if not done yet. if (atkTextAttributeInvalid == ATK_TEXT_ATTR_INVALID) @@ -231,7 +231,7 @@ static AtkAttributeSet* attributeSetDifference(AtkAttributeSet* attributeSet1, A AtkAttributeSet* currentSet = attributeSet1; AtkAttributeSet* found; - AtkAttributeSet* toDelete = 0; + AtkAttributeSet* toDelete = nullptr; while (currentSet) { found = g_slist_find_custom(attributeSet2, currentSet->data, (GCompareFunc)compareAttribute); @@ -270,8 +270,8 @@ static guint accessibilityObjectLength(const AccessibilityObject* object) // for those cases when it's needed to take it into account // separately (as in getAccessibilityObjectForOffset) RenderObject* renderer = object->renderer(); - if (renderer && renderer->isListMarker()) { - RenderListMarker& marker = toRenderListMarker(*renderer); + if (is<RenderListMarker>(renderer)) { + auto& marker = downcast<RenderListMarker>(*renderer); return marker.text().length() + marker.suffix().length(); } @@ -318,7 +318,7 @@ static const AccessibilityObject* getAccessibilityObjectForOffset(const Accessib return result; } -static AtkAttributeSet* getRunAttributesFromAccesibilityObject(const AccessibilityObject* element, gint offset, gint* startOffset, gint* endOffset) +static AtkAttributeSet* getRunAttributesFromAccessibilityObject(const AccessibilityObject* element, gint offset, gint* startOffset, gint* endOffset) { const AccessibilityObject* child = getAccessibilityObjectForOffset(element, offset, startOffset, endOffset); if (!child) { @@ -363,8 +363,8 @@ static int offsetAdjustmentForListItem(const AccessibilityObject* object) // We need to adjust the offsets for the list item marker in // Left-To-Right text, since we expose it together with the text. RenderObject* renderer = object->renderer(); - if (renderer && renderer->isListItem() && renderer->style().direction() == LTR) - return toRenderListItem(renderer)->markerTextWithSuffix().length(); + if (is<RenderListItem>(renderer) && renderer->style().direction() == LTR) + return downcast<RenderListItem>(*renderer).markerTextWithSuffix().length(); return 0; } @@ -495,8 +495,8 @@ static gchar* webkitAccessibleTextGetText(AtkText* text, gint startOffset, gint int actualEndOffset = endOffset == -1 ? ret.length() : endOffset; if (coreObject->roleValue() == ListItemRole) { RenderObject* objRenderer = coreObject->renderer(); - if (objRenderer && objRenderer->isListItem()) { - String markerText = toRenderListItem(objRenderer)->markerTextWithSuffix(); + if (is<RenderListItem>(objRenderer)) { + String markerText = downcast<RenderListItem>(*objRenderer).markerTextWithSuffix(); ret = objRenderer->style().direction() == LTR ? markerText + ret : ret + markerText; if (endOffset == -1) actualEndOffset = ret.length() + markerText.length(); @@ -601,7 +601,7 @@ static VisibleSelection wordAtPositionForAtkBoundary(const AccessibilityObject* // as when at the beginning of a whitespace range between two "real" words, // since that whitespace is considered a "word" as well. And in case we are // already at the beginning of a "real" word we do not need to look backwards. - if (isStartOfWord(position) && isWhitespace(position.characterBefore())) + if (isStartOfWord(position) && deprecatedIsEditingWhitespace(position.characterBefore())) startPosition = position; else startPosition = previousWordPosition(position); @@ -729,7 +729,7 @@ static bool isWhiteSpaceBetweenSentences(const VisiblePosition& position) if (position.isNull()) return false; - if (!isWhitespace(position.characterAfter())) + if (!deprecatedIsEditingWhitespace(position.characterAfter())) return false; VisiblePosition startOfWhiteSpace = startOfWord(position, RightWordIfOnBoundary); @@ -764,12 +764,12 @@ static VisibleSelection sentenceAtPositionForAtkBoundary(const AccessibilityObje // startOfSentence returns a position after any white space previous to // the sentence, so we might need to adjust that offset for this boundary. - if (isWhitespace(startPosition.characterBefore())) + if (deprecatedIsEditingWhitespace(startPosition.characterBefore())) startPosition = startOfWord(startPosition, LeftWordIfOnBoundary); // endOfSentence returns a position after any white space after the // sentence, so we might need to adjust that offset for this boundary. - if (isWhitespace(endPosition.characterBefore())) + if (deprecatedIsEditingWhitespace(endPosition.characterBefore())) endPosition = startOfWord(endPosition, LeftWordIfOnBoundary); // Finally, do some additional adjustments that might be needed if @@ -1055,7 +1055,7 @@ static AtkAttributeSet* webkitAccessibleTextGetRunAttributes(AtkText* text, gint if (offset == -1) offset = atk_text_get_caret_offset(text); - result = getRunAttributesFromAccesibilityObject(coreObject, offset, startOffset, endOffset); + result = getRunAttributesFromAccessibilityObject(coreObject, offset, startOffset, endOffset); if (*startOffset < 0) { *startOffset = offset; @@ -1233,29 +1233,9 @@ static gboolean webkitAccessibleTextRemoveSelection(AtkText* text, gint selectio static gboolean webkitAccessibleTextSetCaretOffset(AtkText* text, gint offset) { - g_return_val_if_fail(ATK_TEXT(text), FALSE); - returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text), FALSE); - - AccessibilityObject* coreObject = core(text); - if (!coreObject->isAccessibilityRenderObject()) - return FALSE; - - // We need to adjust the offsets for the list item marker. - int offsetAdjustment = offsetAdjustmentForListItem(coreObject); - if (offsetAdjustment) { - if (offset < offsetAdjustment) - return FALSE; - - offset = atkOffsetToWebCoreOffset(text, offset); - } - - PlainTextRange textRange(offset, 0); - VisiblePositionRange range = coreObject->visiblePositionRangeForRange(textRange); - if (range.isNull()) - return FALSE; - - coreObject->setSelectedVisiblePositionRange(range); - return TRUE; + // Internally, setting the caret offset is equivalent to set a zero-length + // selection, so delegate in that implementation and void duplicated code. + return webkitAccessibleTextSetSelection(text, 0, offset, offset); } #if ATK_CHECK_VERSION(2, 10, 0) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.h index d7c7376e4..f9f9de071 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceText_h -#define WebKitAccessibleInterfaceText_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -28,5 +27,4 @@ void webkitAccessibleTextInterfaceInit(AtkTextIface*); -#endif -#endif // WebKitAccessibleInterfaceText_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.cpp index 19c6cf003..ac582fa66 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.cpp @@ -26,6 +26,7 @@ #include "HTMLNames.h" #include "WebKitAccessibleUtil.h" #include "WebKitAccessibleWrapperAtk.h" +#include <wtf/text/CString.h> using namespace WebCore; @@ -37,6 +38,83 @@ static AccessibilityObject* core(AtkValue* value) return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(value)); } +static bool webkitAccessibleSetNewValue(AtkValue* coreValue, const gdouble newValue) +{ + AccessibilityObject* coreObject = core(coreValue); + if (!coreObject->canSetValueAttribute()) + return FALSE; + + // Check value against range limits + double value; + value = std::max(static_cast<double>(coreObject->minValueForRange()), newValue); + value = std::min(static_cast<double>(coreObject->maxValueForRange()), newValue); + + coreObject->setValue(String::number(value)); + return TRUE; +} + +static float webkitAccessibleGetIncrementValue(AccessibilityObject* coreObject) +{ + if (!coreObject->getAttribute(HTMLNames::stepAttr).isEmpty()) + return coreObject->stepValueForRange(); + + // If 'step' attribute is not defined, WebCore assumes a 5% of the + // range between minimum and maximum values. Implicit value of step should be one or larger. + float step = (coreObject->maxValueForRange() - coreObject->minValueForRange()) * 0.05; + return step < 1 ? 1 : step; +} + +#if ATK_CHECK_VERSION(2,11,92) +static void webkitAccessibleGetValueAndText(AtkValue* value, gdouble* currentValue, gchar** alternativeText) +{ + g_return_if_fail(ATK_VALUE(value)); + returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); + + AccessibilityObject* coreObject = core(value); + if (!coreObject) + return; + + if (currentValue) + *currentValue = coreObject->valueForRange(); + if (alternativeText) + *alternativeText = g_strdup_printf("%s", coreObject->valueDescription().utf8().data()); +} + +static double webkitAccessibleGetIncrement(AtkValue* value) +{ + g_return_val_if_fail(ATK_VALUE(value), 0); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value), 0); + + AccessibilityObject* coreObject = core(value); + if (!coreObject) + return 0; + + return webkitAccessibleGetIncrementValue(coreObject); +} + +static void webkitAccessibleSetValue(AtkValue* value, const gdouble newValue) +{ + g_return_if_fail(ATK_VALUE(value)); + returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); + + webkitAccessibleSetNewValue(value, newValue); +} + +static AtkRange* webkitAccessibleGetRange(AtkValue* value) +{ + g_return_val_if_fail(ATK_VALUE(value), nullptr); + returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value), nullptr); + + AccessibilityObject* coreObject = core(value); + if (!coreObject) + return nullptr; + + gdouble minValue = coreObject->minValueForRange(); + gdouble maxValue = coreObject->maxValueForRange(); + gchar* valueDescription = g_strdup_printf("%s", coreObject->valueDescription().utf8().data()); + return atk_range_new(minValue, maxValue, valueDescription); +} +#endif static void webkitAccessibleValueGetCurrentValue(AtkValue* value, GValue* gValue) { g_return_if_fail(ATK_VALUE(value)); @@ -92,16 +170,7 @@ static gboolean webkitAccessibleValueSetCurrentValue(AtkValue* value, const GVal else return FALSE; - AccessibilityObject* coreObject = core(value); - if (!coreObject->canSetValueAttribute()) - return FALSE; - - // Check value against range limits - newValue = std::max(static_cast<double>(coreObject->minValueForRange()), newValue); - newValue = std::min(static_cast<double>(coreObject->maxValueForRange()), newValue); - - coreObject->setValue(String::number(newValue)); - return TRUE; + return webkitAccessibleSetNewValue(value, newValue); } static void webkitAccessibleValueGetMinimumIncrement(AtkValue* value, GValue* gValue) @@ -113,19 +182,17 @@ static void webkitAccessibleValueGetMinimumIncrement(AtkValue* value, GValue* gV g_value_init(gValue, G_TYPE_FLOAT); AccessibilityObject* coreObject = core(value); - if (!coreObject->getAttribute(HTMLNames::stepAttr).isEmpty()) { - g_value_set_float(gValue, coreObject->stepValueForRange()); - return; - } - - // If 'step' attribute is not defined, WebCore assumes a 5% of the - // range between minimum and maximum values. Implicit value of step should be one or larger. - float step = (coreObject->maxValueForRange() - coreObject->minValueForRange()) * 0.05; - g_value_set_float(gValue, step < 1 ? 1 : step); + g_value_set_float(gValue, webkitAccessibleGetIncrementValue(coreObject)); } void webkitAccessibleValueInterfaceInit(AtkValueIface* iface) { +#if ATK_CHECK_VERSION(2,11,92) + iface->get_value_and_text = webkitAccessibleGetValueAndText; + iface->get_increment = webkitAccessibleGetIncrement; + iface->set_value = webkitAccessibleSetValue; + iface->get_range = webkitAccessibleGetRange; +#endif iface->get_current_value = webkitAccessibleValueGetCurrentValue; iface->get_maximum_value = webkitAccessibleValueGetMaximumValue; iface->get_minimum_value = webkitAccessibleValueGetMinimumValue; diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.h b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.h index 6e53551ec..f1b49ebeb 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceValue.h @@ -17,8 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleInterfaceValue_h -#define WebKitAccessibleInterfaceValue_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -26,5 +25,4 @@ void webkitAccessibleValueInterfaceInit(AtkValueIface*); -#endif -#endif // WebKitAccessibleInterfaceValue_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.cpp index 58147fa8c..001f9d06f 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.cpp @@ -159,11 +159,14 @@ bool selectionBelongsToObject(AccessibilityObject* coreObject, VisibleSelection& // AND that the selection is not just "touching" one of the // boundaries for the selected node. We want to check whether the // node is actually inside the region, at least partially. - Node* node = coreObject->node(); - Node* lastDescendant = node->lastDescendant(); - return (range->intersectsNode(node, IGNORE_EXCEPTION) - && (range->endContainer() != node || range->endOffset()) - && (range->startContainer() != lastDescendant || range->startOffset() != lastOffsetInNode(lastDescendant))); + auto& node = *coreObject->node(); + auto* lastDescendant = node.lastDescendant(); + unsigned lastOffset = lastOffsetInNode(lastDescendant); + auto intersectsResult = range->intersectsNode(node); + return !intersectsResult.hasException() + && intersectsResult.releaseReturnValue() + && (&range->endContainer() != &node || range->endOffset()) + && (&range->startContainer() != lastDescendant || range->startOffset() != lastOffset); } #endif diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.h b/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.h index d0312dcd1..a946001f4 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleUtil_h -#define WebKitAccessibleUtil_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -61,7 +60,7 @@ class VisibleSelection; AtkAttributeSet* addToAtkAttributeSet(AtkAttributeSet*, const char* name, const char* value); -void contentsRelativeToAtkCoordinateType(WebCore::AccessibilityObject*, AtkCoordType, WebCore::IntRect, gint* x, gint* y, gint* width = 0, gint* height = 0); +void contentsRelativeToAtkCoordinateType(WebCore::AccessibilityObject*, AtkCoordType, WebCore::IntRect, gint* x, gint* y, gint* width = nullptr, gint* height = nullptr); String accessibilityTitle(WebCore::AccessibilityObject*); @@ -69,5 +68,4 @@ String accessibilityDescription(WebCore::AccessibilityObject*); bool selectionBelongsToObject(WebCore::AccessibilityObject*, WebCore::VisibleSelection&); -#endif -#endif // WebKitAccessibleUtil_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp index 79eb46d35..86cee4e25 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp @@ -37,13 +37,17 @@ #include "AXObjectCache.h" #include "AccessibilityList.h" #include "AccessibilityListBoxOption.h" +#include "AccessibilityTable.h" #include "Document.h" #include "Frame.h" #include "FrameView.h" #include "HTMLNames.h" #include "HTMLTableElement.h" #include "HostWindow.h" +#include "RenderAncestorIterator.h" +#include "RenderFieldset.h" #include "RenderObject.h" +#include "SVGElement.h" #include "Settings.h" #include "TextIterator.h" #include "VisibleUnits.h" @@ -57,6 +61,7 @@ #include "WebKitAccessibleInterfaceImage.h" #include "WebKitAccessibleInterfaceSelection.h" #include "WebKitAccessibleInterfaceTable.h" +#include "WebKitAccessibleInterfaceTableCell.h" #include "WebKitAccessibleInterfaceText.h" #include "WebKitAccessibleInterfaceValue.h" #include "WebKitAccessibleUtil.h" @@ -64,10 +69,6 @@ #include <glib/gprintf.h> #include <wtf/text/CString.h> -#if PLATFORM(GTK) -#include <gtk/gtk.h> -#endif - using namespace WebCore; struct _WebKitAccessiblePrivate { @@ -93,7 +94,7 @@ struct _WebKitAccessiblePrivate { static AccessibilityObject* fallbackObject() { - static AccessibilityObject* object = AccessibilityListBoxOption::create().leakRef(); + static AccessibilityObject* object = &AccessibilityListBoxOption::create().leakRef(); return object; } @@ -110,58 +111,24 @@ static const gchar* webkitAccessibleGetName(AtkObject* object) g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0); - AccessibilityObject* coreObject = core(object); - - if (!coreObject->isAccessibilityRenderObject()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, coreObject->stringValue()); + Vector<AccessibilityText> textOrder; + core(object)->accessibilityText(textOrder); - if (coreObject->isFieldset()) { - AccessibilityObject* label = coreObject->titleUIElement(); - if (label) { - AtkObject* atkObject = label->wrapper(); - if (ATK_IS_TEXT(atkObject)) - return atk_text_get_text(ATK_TEXT(atkObject), 0, -1); - } - } - - if (coreObject->isControl()) { - AccessibilityObject* label = coreObject->correspondingLabelForControlElement(); - if (label) { - AtkObject* atkObject = label->wrapper(); - if (ATK_IS_TEXT(atkObject)) - return atk_text_get_text(ATK_TEXT(atkObject), 0, -1); - } - - // Try text under the node. - String textUnder = coreObject->textUnderElement(); - if (textUnder.length()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, textUnder); - } - - if (coreObject->isImage() || coreObject->isInputImage()) { - Node* node = coreObject->node(); - if (node && node->isHTMLElement()) { - // Get the attribute rather than altText String so as not to fall back on title. - String alt = toHTMLElement(node)->getAttribute(HTMLNames::altAttr); - if (!alt.isEmpty()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, alt); - } - } + for (const auto& text : textOrder) { + // FIXME: This check is here because AccessibilityNodeObject::titleElementText() + // appends an empty String for the LabelByElementText source when there is a + // titleUIElement(). Removing this check makes some fieldsets lose their name. + if (text.text.isEmpty()) + continue; - // Fallback for the webArea object: just return the document's title. - if (coreObject->isWebArea()) { - Document* document = coreObject->document(); - if (document) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, document->title()); + // WebCore Accessibility should provide us with the text alternative computation + // in the order defined by that spec. So take the first thing that our platform + // does not expose via the AtkObject description. + if (text.textSource != HelpText && text.textSource != SummaryText) + return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, text.text); } - // Nothing worked so far, try with the AccessibilityObject's - // title() before going ahead with stringValue(). - String axTitle = accessibilityTitle(coreObject); - if (!axTitle.isEmpty()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, axTitle); - - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, coreObject->stringValue()); + return cacheAndReturnAtkProperty(object, AtkCachedAccessibleName, ""); } static const gchar* webkitAccessibleGetDescription(AtkObject* object) @@ -169,27 +136,26 @@ static const gchar* webkitAccessibleGetDescription(AtkObject* object) g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0); - AccessibilityObject* coreObject = core(object); - Node* node = 0; - if (coreObject->isAccessibilityRenderObject()) - node = coreObject->node(); - if (!node || !node->isHTMLElement() || coreObject->ariaRoleAttribute() != UnknownRole || coreObject->isImage()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, accessibilityDescription(coreObject)); - - // atk_table_get_summary returns an AtkObject. We have no summary object, so expose summary here. - if (coreObject->roleValue() == TableRole) { - String summary = toHTMLTableElement(node)->summary(); - if (!summary.isEmpty()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, summary); - } + Vector<AccessibilityText> textOrder; + core(object)->accessibilityText(textOrder); + + bool nameTextAvailable = false; + for (const auto& text : textOrder) { + // WebCore Accessibility should provide us with the text alternative computation + // in the order defined by that spec. So take the first thing that our platform + // does not expose via the AtkObject name. + if (text.textSource == HelpText || text.textSource == SummaryText) + return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, text.text); - // The title attribute should be reliably available as the object's descripton. - // We do not want to fall back on other attributes in its absence. See bug 25524. - String title = toHTMLElement(node)->title(); - if (!title.isEmpty()) - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, title); + // If there is no other text alternative, the title tag contents will have been + // used for the AtkObject name. We don't want to duplicate it here. + if (text.textSource == TitleTagText && nameTextAvailable) + return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, text.text); - return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, accessibilityDescription(coreObject)); + nameTextAvailable = true; + } + + return cacheAndReturnAtkProperty(object, AtkCachedAccessibleDescription, ""); } static void removeAtkRelationByType(AtkRelationSet* relationSet, AtkRelationType relationType) @@ -206,57 +172,56 @@ static void removeAtkRelationByType(AtkRelationSet* relationSet, AtkRelationType static void setAtkRelationSetFromCoreObject(AccessibilityObject* coreObject, AtkRelationSet* relationSet) { - if (coreObject->isFieldset()) { - AccessibilityObject* label = coreObject->titleUIElement(); - if (label) { - removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY); - atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper()); - } - return; - } - - if (coreObject->roleValue() == LegendRole) { - for (AccessibilityObject* parent = coreObject->parentObjectUnignored(); parent; parent = parent->parentObjectUnignored()) { - if (parent->isFieldset()) { - atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, parent->wrapper()); - break; - } - } - return; - } + // FIXME: We're not implementing all the relation types, most notably the inverse/reciprocal + // types. Filed as bug 155494. + // Elements with aria-labelledby should have the labelled-by relation as per the ARIA AAM spec. + // Controls with a label element and fieldsets with a legend element should also use this relation + // as per the HTML AAM spec. The reciprocal label-for relation should also be used. + removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY); if (coreObject->isControl()) { - AccessibilityObject* label = coreObject->correspondingLabelForControlElement(); - if (label) { - removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY); + if (AccessibilityObject* label = coreObject->correspondingLabelForControlElement()) atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper()); + } else if (coreObject->isFieldset()) { + if (AccessibilityObject* label = coreObject->titleUIElement()) + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper()); + } else if (coreObject->roleValue() == LegendRole) { + if (RenderFieldset* renderFieldset = ancestorsOfType<RenderFieldset>(*coreObject->renderer()).first()) { + AccessibilityObject* fieldset = coreObject->axObjectCache()->getOrCreate(renderFieldset); + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, fieldset->wrapper()); } + } else if (AccessibilityObject* control = coreObject->correspondingControlForLabelElement()) { + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, control->wrapper()); } else { - AccessibilityObject* control = coreObject->correspondingControlForLabelElement(); - if (control) - atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, control->wrapper()); + AccessibilityObject::AccessibilityChildrenVector ariaLabelledByElements; + coreObject->ariaLabelledByElements(ariaLabelledByElements); + for (const auto& accessibilityObject : ariaLabelledByElements) + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, accessibilityObject->wrapper()); } - // Check whether object supports aria-flowto - if (coreObject->supportsARIAFlowTo()) { - removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_TO); - AccessibilityObject::AccessibilityChildrenVector ariaFlowToElements; - coreObject->ariaFlowToElements(ariaFlowToElements); - for (const auto& accessibilityObject : ariaFlowToElements) - atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO, accessibilityObject->wrapper()); - } - - // Check whether object supports aria-describedby. It provides an additional information for the user. - if (coreObject->supportsARIADescribedBy()) { - removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIBED_BY); - AccessibilityObject::AccessibilityChildrenVector ariaDescribedByElements; - coreObject->ariaDescribedByElements(ariaDescribedByElements); - for (const auto& accessibilityObject : ariaDescribedByElements) - atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY, accessibilityObject->wrapper()); - } + // Elements with aria-flowto should have the flows-to relation as per the ARIA AAM spec. + removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_TO); + AccessibilityObject::AccessibilityChildrenVector ariaFlowToElements; + coreObject->ariaFlowToElements(ariaFlowToElements); + for (const auto& accessibilityObject : ariaFlowToElements) + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO, accessibilityObject->wrapper()); + + // Elements with aria-describedby should have the described-by relation as per the ARIA AAM spec. + removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIBED_BY); + AccessibilityObject::AccessibilityChildrenVector ariaDescribedByElements; + coreObject->ariaDescribedByElements(ariaDescribedByElements); + for (const auto& accessibilityObject : ariaDescribedByElements) + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY, accessibilityObject->wrapper()); + + // Elements with aria-controls should have the controller-for relation as per the ARIA AAM spec. + removeAtkRelationByType(relationSet, ATK_RELATION_CONTROLLER_FOR); + AccessibilityObject::AccessibilityChildrenVector ariaControls; + coreObject->ariaControlsElements(ariaControls); + for (const auto& accessibilityObject : ariaControls) + atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_CONTROLLER_FOR, accessibilityObject->wrapper()); } -static gpointer webkitAccessibleParentClass = 0; +static gpointer webkitAccessibleParentClass = nullptr; static bool isRootObject(AccessibilityObject* coreObject) { @@ -284,18 +249,6 @@ static AtkObject* atkParentOfRootObject(AtkObject* object) Document* document = coreObject->document(); if (!document) return 0; - -#if PLATFORM(GTK) - HostWindow* hostWindow = document->view()->hostWindow(); - if (hostWindow) { - PlatformPageClient scrollView = hostWindow->platformPageClient(); - if (scrollView) { - GtkWidget* scrollViewParent = gtk_widget_get_parent(scrollView); - if (scrollViewParent) - return gtk_widget_get_accessible(scrollViewParent); - } - } -#endif // PLATFORM(GTK) } if (!coreParent) @@ -327,31 +280,9 @@ static AtkObject* webkitAccessibleGetParent(AtkObject* object) if (!coreParent) return 0; - // We don't expose table rows to Assistive technologies, but we - // need to have them anyway in the hierarchy from WebCore to - // properly perform coordinates calculations when requested. - if (coreParent->isTableRow() && coreObject->isTableCell()) - coreParent = coreParent->parentObjectUnignored(); - return coreParent->wrapper(); } -static gint getNChildrenForTable(AccessibilityObject* coreObject) -{ - const AccessibilityObject::AccessibilityChildrenVector& tableChildren = coreObject->children(); - size_t cellsCount = 0; - - // Look for the actual index of the cell inside the table. - for (const auto& tableChild : tableChildren) { - if (tableChild->isTableRow()) - cellsCount += tableChild->children().size(); - else - cellsCount++; - } - - return cellsCount; -} - static gint webkitAccessibleGetNChildren(AtkObject* object) { g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0); @@ -359,38 +290,9 @@ static gint webkitAccessibleGetNChildren(AtkObject* object) AccessibilityObject* coreObject = core(object); - // Tables should be treated in a different way because rows should - // be bypassed when exposing the accessible hierarchy. - if (coreObject->isAccessibilityTable()) - return getNChildrenForTable(coreObject); - return coreObject->children().size(); } -static AccessibilityObject* getChildForTable(AccessibilityObject* coreObject, gint index) -{ - const AccessibilityObject::AccessibilityChildrenVector& tableChildren = coreObject->children(); - size_t cellsCount = 0; - - // Look for the actual index of the cell inside the table. - size_t current = static_cast<size_t>(index); - for (const auto& tableChild : tableChildren) { - if (tableChild->isTableRow()) { - const AccessibilityObject::AccessibilityChildrenVector& rowChildren = tableChild->children(); - size_t rowChildrenCount = rowChildren.size(); - if (current < cellsCount + rowChildrenCount) - return rowChildren.at(current - cellsCount).get(); - cellsCount += rowChildrenCount; - } else if (cellsCount == current) - return tableChild.get(); - else - cellsCount++; - } - - // Shouldn't reach if the child was found. - return 0; -} - static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index) { g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0); @@ -400,18 +302,12 @@ static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index) return 0; AccessibilityObject* coreObject = core(object); - AccessibilityObject* coreChild = 0; - - // Tables are special cases because rows should be bypassed, but - // still taking their cells into account. - if (coreObject->isAccessibilityTable()) - coreChild = getChildForTable(coreObject, index); - else { - const AccessibilityObject::AccessibilityChildrenVector& children = coreObject->children(); - if (static_cast<unsigned>(index) >= children.size()) - return 0; - coreChild = children.at(index).get(); - } + AccessibilityObject* coreChild = nullptr; + + const AccessibilityObject::AccessibilityChildrenVector& children = coreObject->children(); + if (static_cast<size_t>(index) >= children.size()) + return 0; + coreChild = children.at(index).get(); if (!coreChild) return 0; @@ -423,40 +319,6 @@ static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index) return child; } -static gint getIndexInParentForCellInRow(AccessibilityObject* coreObject) -{ - AccessibilityObject* parent = coreObject->parentObjectUnignored(); - if (!parent) - return -1; - - AccessibilityObject* grandParent = parent->parentObjectUnignored(); - if (!grandParent) - return -1; - - const AccessibilityObject::AccessibilityChildrenVector& rows = grandParent->children(); - size_t previousCellsCount = 0; - - // Look for the actual index of the cell inside the table. - for (const auto& row : rows) { - if (!row->isTableRow()) - continue; - - const AccessibilityObject::AccessibilityChildrenVector& cells = row->children(); - size_t cellsCount = cells.size(); - - if (row == parent) { - for (unsigned j = 0; j < cellsCount; ++j) { - if (cells[j] == coreObject) - return previousCellsCount + j; - } - } - - previousCellsCount += cellsCount; - } - - return -1; -} - static gint webkitAccessibleGetIndexInParent(AtkObject* object) { g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), -1); @@ -480,11 +342,6 @@ static gint webkitAccessibleGetIndexInParent(AtkObject* object) } } - // Need to calculate the index of the cell in the table, as - // rows won't be exposed to assistive technologies. - if (parent && parent->isTableRow() && coreObject->isTableCell()) - return getIndexInParentForCellInRow(coreObject); - if (!parent) return -1; @@ -497,11 +354,9 @@ static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object) g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0); - AtkAttributeSet* attributeSet = 0; + AtkAttributeSet* attributeSet = nullptr; #if PLATFORM(GTK) attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitGtk"); -#elif PLATFORM(EFL) - attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitEfl"); #endif AccessibilityObject* coreObject = core(object); @@ -511,9 +366,12 @@ static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object) // Hack needed for WebKit2 tests because obtaining an element by its ID // cannot be done from the UIProcess. Assistive technologies have no need // for this information. - Node* node = coreObject->node(); - if (node && node->isElementNode()) { - String id = toElement(node)->getIdAttribute().string(); + Element* element = coreObject->element() ? coreObject->element() : coreObject->actionElement(); + if (element) { + String tagName = element->tagName(); + if (!tagName.isEmpty()) + attributeSet = addToAtkAttributeSet(attributeSet, "tag", tagName.convertToASCIILowercase().utf8().data()); + String id = element->getIdAttribute().string(); if (!id.isEmpty()) attributeSet = addToAtkAttributeSet(attributeSet, "html-id", id.utf8().data()); } @@ -524,9 +382,16 @@ static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object) attributeSet = addToAtkAttributeSet(attributeSet, "level", value.utf8().data()); } + if (coreObject->roleValue() == MathElementRole) { + if (coreObject->isMathMultiscriptObject(PreSuperscript) || coreObject->isMathMultiscriptObject(PreSubscript)) + attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "pre"); + else if (coreObject->isMathMultiscriptObject(PostSuperscript) || coreObject->isMathMultiscriptObject(PostSubscript)) + attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "post"); + } + // Set the 'layout-guess' attribute to help Assistive // Technologies know when an exposed table is not data table. - if (coreObject->isAccessibilityTable() && !coreObject->isDataTable()) + if (is<AccessibilityTable>(*coreObject) && downcast<AccessibilityTable>(*coreObject).isExposableThroughAccessibility() && !coreObject->isDataTable()) attributeSet = addToAtkAttributeSet(attributeSet, "layout-guess", "true"); String placeholder = coreObject->placeholderValue(); @@ -543,32 +408,38 @@ static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object) attributeSet = addToAtkAttributeSet(attributeSet, "sort", sortAttribute.string().utf8().data()); } - // Landmarks will be exposed with xml-roles object attributes, with the exception - // of LandmarkApplicationRole, which will be exposed with ATK_ROLE_EMBEDDED. - AccessibilityRole role = coreObject->roleValue(); - switch (role) { - case LandmarkBannerRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "banner"); - break; - case LandmarkComplementaryRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "complementary"); - break; - case LandmarkContentInfoRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "contentinfo"); - break; - case LandmarkMainRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "main"); - break; - case LandmarkNavigationRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "navigation"); - break; - case LandmarkSearchRole: - attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "search"); - break; - default: - break; + if (coreObject->supportsARIAPosInSet()) + attributeSet = addToAtkAttributeSet(attributeSet, "posinset", String::number(coreObject->ariaPosInSet()).utf8().data()); + + if (coreObject->supportsARIASetSize()) + attributeSet = addToAtkAttributeSet(attributeSet, "setsize", String::number(coreObject->ariaSetSize()).utf8().data()); + + String isReadOnly = coreObject->ariaReadOnlyValue(); + if (!isReadOnly.isEmpty()) + attributeSet = addToAtkAttributeSet(attributeSet, "readonly", isReadOnly.utf8().data()); + + String valueDescription = coreObject->valueDescription(); + if (!valueDescription.isEmpty()) + attributeSet = addToAtkAttributeSet(attributeSet, "valuetext", valueDescription.utf8().data()); + + // According to the W3C Core Accessibility API Mappings 1.1, section 5.4.1 General Rules: + // "User agents must expose the WAI-ARIA role string if the API supports a mechanism to do so." + // In the case of ATK, the mechanism to do so is an object attribute pair (xml-roles:"string"). + // The computedRoleString is primarily for testing, and not limited to elements with ARIA roles. + // Because the computedRoleString currently contains the ARIA role string, we'll use it for + // both purposes, as the "computed-role" object attribute for all elements which have a value + // and also via the "xml-roles" attribute for elements with ARIA, as well as for landmarks. + String roleString = coreObject->computedRoleString(); + if (!roleString.isEmpty()) { + if (coreObject->ariaRoleAttribute() != UnknownRole || coreObject->isLandmark()) + attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", roleString.utf8().data()); + attributeSet = addToAtkAttributeSet(attributeSet, "computed-role", roleString.utf8().data()); } + String roleDescription = coreObject->roleDescription(); + if (!roleDescription.isEmpty()) + attributeSet = addToAtkAttributeSet(attributeSet, "roledescription", roleDescription.utf8().data()); + return attributeSet; } @@ -586,10 +457,17 @@ static AtkRole atkRole(AccessibilityObject* coreObject) case UnknownRole: return ATK_ROLE_UNKNOWN; case AudioRole: +#if ATK_CHECK_VERSION(2, 11, 3) + return ATK_ROLE_AUDIO; +#endif case VideoRole: +#if ATK_CHECK_VERSION(2, 11, 3) + return ATK_ROLE_VIDEO; +#endif return ATK_ROLE_EMBEDDED; case ButtonRole: return ATK_ROLE_PUSH_BUTTON; + case SwitchRole: case ToggleButtonRole: return ATK_ROLE_TOGGLE_BUTTON; case RadioButtonRole: @@ -603,9 +481,14 @@ static AtkRole atkRole(AccessibilityObject* coreObject) return ATK_ROLE_PAGE_TAB_LIST; case TextFieldRole: case TextAreaRole: + case SearchFieldRole: return ATK_ROLE_ENTRY; case StaticTextRole: +#if ATK_CHECK_VERSION(2, 15, 2) + return ATK_ROLE_STATIC; +#else return ATK_ROLE_TEXT; +#endif case OutlineRole: case TreeRole: return ATK_ROLE_TREE; @@ -627,15 +510,13 @@ static AtkRole atkRole(AccessibilityObject* coreObject) // return ATK_ROLE_TABLE_COLUMN_HEADER; // Is this right? return ATK_ROLE_UNKNOWN; // Matches Mozilla case RowRole: - // return ATK_ROLE_TABLE_ROW_HEADER; // Is this right? - return ATK_ROLE_LIST_ITEM; // Matches Mozilla + return ATK_ROLE_TABLE_ROW; case ToolbarRole: return ATK_ROLE_TOOL_BAR; case BusyIndicatorRole: return ATK_ROLE_PROGRESS_BAR; // Is this right? case ProgressIndicatorRole: - // return ATK_ROLE_SPIN_BUTTON; // Some confusion about this role in AccessibilityRenderObject.cpp - return ATK_ROLE_PROGRESS_BAR; + return coreObject->isMeter() ? ATK_ROLE_LEVEL_BAR : ATK_ROLE_PROGRESS_BAR; case WindowRole: return ATK_ROLE_WINDOW; case PopUpButtonRole: @@ -646,31 +527,42 @@ static AtkRole atkRole(AccessibilityObject* coreObject) case SplitterRole: return ATK_ROLE_SEPARATOR; case ColorWellRole: - return ATK_ROLE_COLOR_CHOOSER; +#if PLATFORM(GTK) + // ATK_ROLE_COLOR_CHOOSER is defined as a dialog (i.e. it's what appears when you push the button). + return ATK_ROLE_PUSH_BUTTON; +#endif case ListRole: return ATK_ROLE_LIST; case ScrollBarRole: return ATK_ROLE_SCROLL_BAR; case ScrollAreaRole: return ATK_ROLE_SCROLL_PANE; - case GridRole: // Is this right? + case GridRole: case TableRole: return ATK_ROLE_TABLE; case ApplicationRole: return ATK_ROLE_APPLICATION; - case GroupRole: case RadioGroupRole: + case SVGRootRole: case TabPanelRole: return ATK_ROLE_PANEL; - case RowHeaderRole: // Row headers are cells after all. - case ColumnHeaderRole: // Column headers are cells after all. + case GroupRole: + return coreObject->isStyleFormatGroup() ? ATK_ROLE_SECTION : ATK_ROLE_PANEL; + case RowHeaderRole: + return ATK_ROLE_ROW_HEADER; + case ColumnHeaderRole: + return ATK_ROLE_COLUMN_HEADER; + case CaptionRole: + return ATK_ROLE_CAPTION; case CellRole: - return ATK_ROLE_TABLE_CELL; + case GridCellRole: + return coreObject->inheritsPresentationalRole() ? ATK_ROLE_SECTION : ATK_ROLE_TABLE_CELL; case LinkRole: case WebCoreLinkRole: case ImageMapLinkRole: return ATK_ROLE_LINK; case ImageMapRole: + return ATK_ROLE_IMAGE_MAP; case ImageRole: return ATK_ROLE_IMAGE; case ListMarkerRole: @@ -686,17 +578,27 @@ static AtkRole atkRole(AccessibilityObject* coreObject) case HeadingRole: return ATK_ROLE_HEADING; case ListBoxRole: - return ATK_ROLE_LIST; + // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-listbox + return coreObject->isDescendantOfRole(ComboBoxRole) ? ATK_ROLE_MENU : ATK_ROLE_LIST_BOX; case ListItemRole: + return coreObject->inheritsPresentationalRole() ? ATK_ROLE_SECTION : ATK_ROLE_LIST_ITEM; case ListBoxOptionRole: - return ATK_ROLE_LIST_ITEM; + return coreObject->isDescendantOfRole(ComboBoxRole) ? ATK_ROLE_MENU_ITEM : ATK_ROLE_LIST_ITEM; case ParagraphRole: return ATK_ROLE_PARAGRAPH; case LabelRole: case LegendRole: return ATK_ROLE_LABEL; + case BlockquoteRole: +#if ATK_CHECK_VERSION(2, 11, 3) + return ATK_ROLE_BLOCK_QUOTE; +#endif case DivRole: + case PreRole: + case SVGTextRole: return ATK_ROLE_SECTION; + case FooterRole: + return ATK_ROLE_FOOTER; case FormRole: return ATK_ROLE_FORM; case CanvasRole: @@ -711,7 +613,7 @@ static AtkRole atkRole(AccessibilityObject* coreObject) return ATK_ROLE_TOOL_TIP; case WebAreaRole: return ATK_ROLE_DOCUMENT_WEB; - case LandmarkApplicationRole: + case WebApplicationRole: return ATK_ROLE_EMBEDDED; #if ATK_CHECK_VERSION(2, 11, 3) case ApplicationLogRole: @@ -724,11 +626,40 @@ static AtkRole atkRole(AccessibilityObject* coreObject) return ATK_ROLE_DEFINITION; case DocumentMathRole: return ATK_ROLE_MATH; + case MathElementRole: + if (coreObject->isMathRow()) + return ATK_ROLE_PANEL; + if (coreObject->isMathTable()) + return ATK_ROLE_TABLE; + if (coreObject->isMathTableRow()) + return ATK_ROLE_TABLE_ROW; + if (coreObject->isMathTableCell()) + return ATK_ROLE_TABLE_CELL; + if (coreObject->isMathSubscriptSuperscript() || coreObject->isMathMultiscript()) + return ATK_ROLE_SECTION; +#if ATK_CHECK_VERSION(2, 15, 4) + if (coreObject->isMathFraction()) + return ATK_ROLE_MATH_FRACTION; + if (coreObject->isMathSquareRoot() || coreObject->isMathRoot()) + return ATK_ROLE_MATH_ROOT; + if (coreObject->isMathScriptObject(Subscript) + || coreObject->isMathMultiscriptObject(PreSubscript) || coreObject->isMathMultiscriptObject(PostSubscript)) + return ATK_ROLE_SUBSCRIPT; + if (coreObject->isMathScriptObject(Superscript) + || coreObject->isMathMultiscriptObject(PreSuperscript) || coreObject->isMathMultiscriptObject(PostSuperscript)) + return ATK_ROLE_SUPERSCRIPT; +#endif +#if ATK_CHECK_VERSION(2, 15, 2) + if (coreObject->isMathToken()) + return ATK_ROLE_STATIC; +#endif + return ATK_ROLE_UNKNOWN; case LandmarkBannerRole: case LandmarkComplementaryRole: case LandmarkContentInfoRole: case LandmarkMainRole: case LandmarkNavigationRole: + case LandmarkRegionRole: case LandmarkSearchRole: return ATK_ROLE_LANDMARK; #endif @@ -740,6 +671,19 @@ static AtkRole atkRole(AccessibilityObject* coreObject) case DescriptionListDetailRole: return ATK_ROLE_DESCRIPTION_VALUE; #endif + case InlineRole: +#if ATK_CHECK_VERSION(2, 15, 4) + if (coreObject->isSubscriptStyleGroup()) + return ATK_ROLE_SUBSCRIPT; + if (coreObject->isSuperscriptStyleGroup()) + return ATK_ROLE_SUPERSCRIPT; +#endif +#if ATK_CHECK_VERSION(2, 15, 2) + return ATK_ROLE_STATIC; + case SVGTextPathRole: + case SVGTSpanRole: + return ATK_ROLE_STATIC; +#endif default: return ATK_ROLE_UNKNOWN; } @@ -803,16 +747,18 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta if (isListBoxOption && coreObject->isSelectedOptionActive()) atk_state_set_add_state(stateSet, ATK_STATE_ACTIVE); + if (coreObject->isBusy()) + atk_state_set_add_state(stateSet, ATK_STATE_BUSY); + +#if ATK_CHECK_VERSION(2,11,2) + if (coreObject->supportsChecked() && coreObject->canSetValueAttribute()) + atk_state_set_add_state(stateSet, ATK_STATE_CHECKABLE); +#endif + if (coreObject->isChecked()) atk_state_set_add_state(stateSet, ATK_STATE_CHECKED); - // FIXME: isReadOnly does not seem to do the right thing for - // controls, so check explicitly for them. In addition, because - // isReadOnly is false for listBoxOptions, we need to add one - // more check so that we do not present them as being "editable". - if ((!coreObject->isReadOnly() - || (coreObject->isControl() && coreObject->canSetValueAttribute())) - && !isListBoxOption) + if ((coreObject->isTextControl() || coreObject->isNonNativeTextControl()) && coreObject->canSetValueAttribute()) atk_state_set_add_state(stateSet, ATK_STATE_EDITABLE); // FIXME: Put both ENABLED and SENSITIVE together here for now @@ -857,6 +803,11 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta if (coreObject->isPressed()) atk_state_set_add_state(stateSet, ATK_STATE_PRESSED); +#if ATK_CHECK_VERSION(2,15,3) + if (!coreObject->canSetValueAttribute() && (coreObject->supportsARIAReadOnly())) + atk_state_set_add_state(stateSet, ATK_STATE_READ_ONLY); +#endif + if (coreObject->isRequired()) atk_state_set_add_state(stateSet, ATK_STATE_REQUIRED); @@ -890,10 +841,10 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta } // Mutually exclusive, so we group these two - if (coreObject->roleValue() == TextFieldRole) - atk_state_set_add_state(stateSet, ATK_STATE_SINGLE_LINE); - else if (coreObject->roleValue() == TextAreaRole) + if (coreObject->roleValue() == TextAreaRole || coreObject->ariaIsMultiline()) atk_state_set_add_state(stateSet, ATK_STATE_MULTI_LINE); + else if (coreObject->roleValue() == TextFieldRole || coreObject->roleValue() == SearchFieldRole) + atk_state_set_add_state(stateSet, ATK_STATE_SINGLE_LINE); // TODO: ATK_STATE_SENSITIVE @@ -965,7 +916,7 @@ static const gchar* webkitAccessibleGetObjectLocale(AtkObject* object) return cacheAndReturnAtkProperty(object, AtkCachedDocumentLocale, language); } else if (ATK_IS_TEXT(object)) { - const gchar* locale = 0; + const gchar* locale = nullptr; AtkAttributeSet* textAttributes = atk_text_get_default_attributes(ATK_TEXT(object)); for (AtkAttributeSet* attributes = textAttributes; attributes; attributes = attributes->next) { @@ -1046,6 +997,9 @@ static const GInterfaceInfo AtkInterfacesInitFunctions[] = { {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleComponentInterfaceInit), 0, 0}, {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleImageInterfaceInit), 0, 0}, {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleTableInterfaceInit), 0, 0}, +#if ATK_CHECK_VERSION(2,11,90) + {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleTableCellInterfaceInit), 0, 0}, +#endif {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleHypertextInterfaceInit), 0, 0}, {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleHyperlinkImplInterfaceInit), 0, 0}, {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleDocumentInterfaceInit), 0, 0}, @@ -1053,43 +1007,50 @@ static const GInterfaceInfo AtkInterfacesInitFunctions[] = { }; enum WAIType { - WAI_ACTION, - WAI_SELECTION, - WAI_EDITABLE_TEXT, - WAI_TEXT, - WAI_COMPONENT, - WAI_IMAGE, - WAI_TABLE, - WAI_HYPERTEXT, - WAI_HYPERLINK, - WAI_DOCUMENT, - WAI_VALUE, + WAIAction, + WAISelection, + WAIEditableText, + WAIText, + WAIComponent, + WAIImage, + WAITable, +#if ATK_CHECK_VERSION(2,11,90) + WAITableCell, +#endif + WAIHypertext, + WAIHyperlink, + WAIDocument, + WAIValue, }; static GType GetAtkInterfaceTypeFromWAIType(WAIType type) { switch (type) { - case WAI_ACTION: + case WAIAction: return ATK_TYPE_ACTION; - case WAI_SELECTION: + case WAISelection: return ATK_TYPE_SELECTION; - case WAI_EDITABLE_TEXT: + case WAIEditableText: return ATK_TYPE_EDITABLE_TEXT; - case WAI_TEXT: + case WAIText: return ATK_TYPE_TEXT; - case WAI_COMPONENT: + case WAIComponent: return ATK_TYPE_COMPONENT; - case WAI_IMAGE: + case WAIImage: return ATK_TYPE_IMAGE; - case WAI_TABLE: + case WAITable: return ATK_TYPE_TABLE; - case WAI_HYPERTEXT: +#if ATK_CHECK_VERSION(2,11,90) + case WAITableCell: + return ATK_TYPE_TABLE_CELL; +#endif + case WAIHypertext: return ATK_TYPE_HYPERTEXT; - case WAI_HYPERLINK: + case WAIHyperlink: return ATK_TYPE_HYPERLINK_IMPL; - case WAI_DOCUMENT: + case WAIDocument: return ATK_TYPE_DOCUMENT; - case WAI_VALUE: + case WAIValue: return ATK_TYPE_VALUE; } @@ -1099,7 +1060,8 @@ static GType GetAtkInterfaceTypeFromWAIType(WAIType type) static bool roleIsTextType(AccessibilityRole role) { return role == ParagraphRole || role == HeadingRole || role == DivRole || role == CellRole - || role == LinkRole || role == WebCoreLinkRole || role == ListItemRole; + || role == LinkRole || role == WebCoreLinkRole || role == ListItemRole || role == PreRole + || role == GridCellRole; } static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) @@ -1107,7 +1069,7 @@ static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) guint16 interfaceMask = 0; // Component interface is always supported - interfaceMask |= 1 << WAI_COMPONENT; + interfaceMask |= 1 << WAIComponent; AccessibilityRole role = coreObject->roleValue(); @@ -1117,68 +1079,71 @@ static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) // object, and only supports having one action per object), it is // better just to implement this interface for every instance of // the WebKitAccessible class and let WebCore decide what to do. - interfaceMask |= 1 << WAI_ACTION; + interfaceMask |= 1 << WAIAction; // Selection - if (coreObject->isListBox() || coreObject->isMenuList()) - interfaceMask |= 1 << WAI_SELECTION; + if (coreObject->canHaveSelectedChildren() || coreObject->isMenuList()) + interfaceMask |= 1 << WAISelection; // Get renderer if available. - RenderObject* renderer = 0; + RenderObject* renderer = nullptr; if (coreObject->isAccessibilityRenderObject()) renderer = coreObject->renderer(); // Hyperlink (links and embedded objects). if (coreObject->isLink() || (renderer && renderer->isReplaced())) - interfaceMask |= 1 << WAI_HYPERLINK; + interfaceMask |= 1 << WAIHyperlink; - // Text & Editable Text + // Text, Editable Text & Hypertext if (role == StaticTextRole || coreObject->isMenuListOption()) - interfaceMask |= 1 << WAI_TEXT; - else { - if (coreObject->isTextControl()) { - interfaceMask |= 1 << WAI_TEXT; - if (!coreObject->isReadOnly()) - interfaceMask |= 1 << WAI_EDITABLE_TEXT; - } else { - if (role != TableRole) { - interfaceMask |= 1 << WAI_HYPERTEXT; - if ((renderer && renderer->childrenInline()) || roleIsTextType(role)) - interfaceMask |= 1 << WAI_TEXT; - } + interfaceMask |= 1 << WAIText; + else if (coreObject->isTextControl() || coreObject->isNonNativeTextControl()) { + interfaceMask |= 1 << WAIText; + if (coreObject->canSetValueAttribute()) + interfaceMask |= 1 << WAIEditableText; + } else if (!coreObject->isWebArea()) { + if (role != TableRole) { + interfaceMask |= 1 << WAIHypertext; + if ((renderer && renderer->childrenInline()) || roleIsTextType(role) || coreObject->isMathToken()) + interfaceMask |= 1 << WAIText; + } - // Add the TEXT interface for list items whose - // first accessible child has a text renderer - if (role == ListItemRole) { - const AccessibilityObject::AccessibilityChildrenVector& children = coreObject->children(); - if (children.size()) { - AccessibilityObject* axRenderChild = children.at(0).get(); - interfaceMask |= getInterfaceMaskFromObject(axRenderChild); - } + // Add the TEXT interface for list items whose + // first accessible child has a text renderer + if (role == ListItemRole) { + const AccessibilityObject::AccessibilityChildrenVector& children = coreObject->children(); + if (children.size()) { + AccessibilityObject* axRenderChild = children.at(0).get(); + interfaceMask |= getInterfaceMaskFromObject(axRenderChild); } } } // Image if (coreObject->isImage()) - interfaceMask |= 1 << WAI_IMAGE; + interfaceMask |= 1 << WAIImage; // Table - if (role == TableRole) - interfaceMask |= 1 << WAI_TABLE; + if (role == TableRole || role == GridRole) + interfaceMask |= 1 << WAITable; + +#if ATK_CHECK_VERSION(2,11,90) + if (role == CellRole || role == ColumnHeaderRole || role == RowHeaderRole) + interfaceMask |= 1 << WAITableCell; +#endif // Document if (role == WebAreaRole) - interfaceMask |= 1 << WAI_DOCUMENT; + interfaceMask |= 1 << WAIDocument; // Value if (role == SliderRole || role == SpinButtonRole || role == ScrollBarRole || role == ProgressIndicatorRole) - interfaceMask |= 1 << WAI_VALUE; + interfaceMask |= 1 << WAIValue; #if ENABLE(INPUT_TYPE_COLOR) // Color type. if (role == ColorWellRole) - interfaceMask |= 1 << WAI_TEXT; + interfaceMask |= 1 << WAIText; #endif return interfaceMask; @@ -1261,18 +1226,6 @@ bool webkitAccessibleIsDetached(WebKitAccessible* accessible) return accessible->m_object == fallbackObject(); } -AtkObject* webkitAccessibleGetFocusedElement(WebKitAccessible* accessible) -{ - if (!accessible->m_object) - return 0; - - RefPtr<AccessibilityObject> focusedObj = accessible->m_object->focusedUIElement(); - if (!focusedObj) - return 0; - - return focusedObj->wrapper(); -} - AccessibilityObject* objectFocusedAndCaretOffsetUnignored(AccessibilityObject* referenceObject, int& offset) { // Indication that something bogus has transpired. @@ -1314,7 +1267,7 @@ AccessibilityObject* objectFocusedAndCaretOffsetUnignored(AccessibilityObject* r if (referenceObject->isDescendantOfObject(firstUnignoredParent)) referenceObject = firstUnignoredParent; - Node* startNode = 0; + Node* startNode = nullptr; if (firstUnignoredParent != referenceObject || firstUnignoredParent->isTextControl()) { // We need to use the first child's node of the reference // object as the start point to calculate the caret offset @@ -1356,7 +1309,7 @@ AccessibilityObject* objectFocusedAndCaretOffsetUnignored(AccessibilityObject* r const char* cacheAndReturnAtkProperty(AtkObject* object, AtkCachedProperty property, String value) { WebKitAccessiblePrivate* priv = WEBKIT_ACCESSIBLE(object)->priv; - CString* propertyPtr = 0; + CString* propertyPtr = nullptr; switch (property) { case AtkCachedAccessibleName: diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.h b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.h index 0d473019d..7dfebfb7f 100644 --- a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.h +++ b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WebKitAccessibleWrapperAtk_h -#define WebKitAccessibleWrapperAtk_h +#pragma once #if HAVE(ACCESSIBILITY) @@ -79,13 +78,10 @@ void webkitAccessibleDetach(WebKitAccessible*); bool webkitAccessibleIsDetached(WebKitAccessible*); -AtkObject* webkitAccessibleGetFocusedElement(WebKitAccessible*); - WebCore::AccessibilityObject* objectFocusedAndCaretOffsetUnignored(WebCore::AccessibilityObject*, int& offset); const char* cacheAndReturnAtkProperty(AtkObject*, AtkCachedProperty, String value); G_END_DECLS -#endif -#endif // WebKitAccessibleWrapperAtk_h +#endif // HAVE(ACCESSIBILITY) |