예제 #1
0
static gint getIndexInParentForCellInRow(AccessibilityObject* coreObject)
{
    AccessibilityObject* parent = coreObject->parentObjectUnignored();
    if (!parent)
        return -1;

    AccessibilityObject* grandParent = parent->parentObjectUnignored();
    if (!grandParent)
        return -1;

    AccessibilityObject::AccessibilityChildrenVector rows = grandParent->children();
    size_t rowsCount = rows.size();
    size_t previousCellsCount = 0;

    // Look for the actual index of the cell inside the table.
    for (unsigned i = 0; i < rowsCount; ++i) {
        if (!rows[i]->isTableRow())
            continue;

        AccessibilityObject::AccessibilityChildrenVector cells = rows[i]->children();
        size_t cellsCount = cells.size();

        if (rows[i] == parent) {
            for (unsigned j = 0; j < cellsCount; ++j) {
                if (cells[j] == coreObject)
                    return previousCellsCount + j;
            }
        }

        previousCellsCount += cellsCount;
    }

    return -1;
}
static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection)
{
    g_return_val_if_fail(ATK_SELECTION(selection), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), 0);

    AccessibilityObject* coreSelection = core(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 = downcast<HTMLSelectElement>(renderer->node())->selectedIndex();
        return selectedIndex >= 0 && selectedIndex < static_cast<int>(downcast<HTMLSelectElement>(renderer->node())->listItems().size());
    }

    return 0;
}
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 0;
}
static gint webkitAccessibleGetIndexInParent(AtkObject* object)
{
    AccessibilityObject* coreObject = core(object);
    AccessibilityObject* parent = coreObject->parentObjectUnignored();

    if (!parent && isRootObject(coreObject)) {
        AtkObject* atkParent = atkParentOfRootObject(object);
        if (!atkParent)
            return -1;

        unsigned count = atk_object_get_n_accessible_children(atkParent);
        for (unsigned i = 0; i < count; ++i) {
            AtkObject* child = atk_object_ref_accessible_child(atkParent, i);
            bool childIsObject = child == object;
            g_object_unref(child);
            if (childIsObject)
                return i;
        }
    }

    // Need to calculate the index of the cell in the table, as
    // rows won't be exposed to assistive technologies in GTK.
    if (parent && parent->isTableRow() && coreObject->isTableCell())
        return getIndexInParentForCellInRow(coreObject);

    AccessibilityObject::AccessibilityChildrenVector children = parent->children();
    unsigned count = children.size();
    for (unsigned i = 0; i < count; ++i) {
        if (children[i] == coreObject)
            return i;
    }

    return -1;
}
예제 #5
0
static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index)
{
    if (index < 0)
        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 {
        AccessibilityObject::AccessibilityChildrenVector children = coreObject->children();
        if (static_cast<unsigned>(index) >= children.size())
            return 0;
        coreChild = children.at(index).get();
    }

    if (!coreChild)
        return 0;

    AtkObject* child = coreChild->wrapper();
    atk_object_set_parent(child, object);
    g_object_ref(child);

    return child;
}
static AccessibilityObject* listObjectForSelection(AtkSelection* selection)
{
    AccessibilityObject* coreSelection = core(selection);

    // Only list boxes and menu lists supported so far.
    if (!coreSelection->isListBox() && !coreSelection->isMenuList())
        return 0;

    // For list boxes the list object is just itself.
    if (coreSelection->isListBox())
        return coreSelection;

    // For menu lists we need to return the first accessible child,
    // with role MenuListPopupRole, since that's the one holding the list
    // of items with role MenuListOptionRole.
    AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children();
    if (!children.size())
        return 0;

    AccessibilityObject* listObject = children.at(0).get();
    if (!listObject->isMenuListPopup())
        return 0;

    return listObject;
}
예제 #7
0
AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* areaElement)
{
    // Find the corresponding accessibility object for the HTMLAreaElement. This should be
    // in the list of children for its corresponding image.
    if (!areaElement)
        return 0;
    
    HTMLImageElement* imageElement = areaElement->imageElement();
    if (!imageElement)
        return 0;
    
    AccessibilityObject* axRenderImage = areaElement->document()->axObjectCache()->getOrCreate(imageElement);
    if (!axRenderImage)
        return 0;
    
    AccessibilityObject::AccessibilityChildrenVector imageChildren = axRenderImage->children();
    unsigned count = imageChildren.size();
    for (unsigned k = 0; k < count; ++k) {
        AccessibilityObject* child = imageChildren[k].get();
        if (!child->isImageMapLink())
            continue;
        
        if (static_cast<AccessibilityImageMapLink*>(child)->areaElement() == areaElement)
            return child;
    }    
    
    return 0;
}
static gboolean webkitAccessibleSelectionSelectAllSelection(AtkSelection* selection)
{
    AccessibilityObject* coreSelection = core(selection);
    if (!coreSelection || !coreSelection->isMultiSelectable())
        return FALSE;

    AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children();
    if (coreSelection->isListBox()) {
        AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection);
        listBox->setSelectedChildren(children);
        AccessibilityObject::AccessibilityChildrenVector selectedItems;
        listBox->selectedChildren(selectedItems);
        return selectedItems.size() == children.size();
    }

    return FALSE;
}
예제 #9
0
static gint getNChildrenForTable(AccessibilityObject* coreObject)
{
    AccessibilityObject::AccessibilityChildrenVector tableChildren = coreObject->children();
    size_t tableChildrenCount = tableChildren.size();
    size_t cellsCount = 0;

    // Look for the actual index of the cell inside the table.
    for (unsigned i = 0; i < tableChildrenCount; ++i) {
        if (tableChildren[i]->isTableRow()) {
            AccessibilityObject::AccessibilityChildrenVector rowChildren = tableChildren[i]->children();
            cellsCount += rowChildren.size();
        } else
            cellsCount++;
    }

    return cellsCount;
}
static AccessibilityTableCell* cellAtIndex(AtkTable* table, gint index)
{
    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        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);
        }
    }
    return 0;
}
static bool childrenContainOnlyStaticText(const AccessibilityObject::AccessibilityChildrenVector& children)
{
    if (!children.size())
        return false;
    for (const auto& child : children) {
        if (child->roleValue() == AccessibilityRole::StaticText)
            continue;
        if (child->roleValue() == AccessibilityRole::Group) {
            if (!childrenContainOnlyStaticText(child->children()))
                return false;
        } else
            return false;
    }
    return true;
}
예제 #12
0
static AccessibilityObject* getChildForTable(AccessibilityObject* coreObject, gint index)
{
    AccessibilityObject::AccessibilityChildrenVector tableChildren = coreObject->children();
    size_t tableChildrenCount = tableChildren.size();
    size_t cellsCount = 0;

    // Look for the actual index of the cell inside the table.
    size_t current = static_cast<size_t>(index);
    for (unsigned i = 0; i < tableChildrenCount; ++i) {
        if (tableChildren[i]->isTableRow()) {
            AccessibilityObject::AccessibilityChildrenVector rowChildren = tableChildren[i]->children();
            size_t rowChildrenCount = rowChildren.size();
            if (current < cellsCount + rowChildrenCount)
                return rowChildren.at(current - cellsCount).get();
            cellsCount += rowChildrenCount;
        } else if (cellsCount == current)
            return tableChildren[i].get();
        else
            cellsCount++;
    }

    // Shouldn't reach if the child was found.
    return 0;
}
static AtkObject* webkit_accessible_table_get_row_header(AtkTable* table, gint row)
{
    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
        static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders);

        unsigned rowCount = allRowHeaders.size();
        for (unsigned k = 0; k < rowCount; ++k) {
            AccessibilityObject* rowObject = allRowHeaders[k]->parentObject();
            if (static_cast<AccessibilityTableRow*>(rowObject)->rowIndex() == row)
                return allRowHeaders[k]->wrapper();
        }
    }
    return 0;
}
static gint webkit_accessible_get_index_in_parent(AtkObject* object)
{
    AccessibilityObject* coreObject = core(object);
    AccessibilityObject* parent = coreObject->parentObjectUnignored();

    g_return_val_if_fail(parent, 0);

    AccessibilityObject::AccessibilityChildrenVector children = parent->children();
    unsigned count = children.size();
    for (unsigned i = 0; i < count; ++i) {
        if (children[i] == coreObject)
            return i;
    }

    return 0;
}
static gboolean webkitAccessibleSelectionClearSelection(AtkSelection* selection)
{
    AccessibilityObject* coreSelection = core(selection);
    if (!coreSelection)
        return FALSE;

    AccessibilityObject::AccessibilityChildrenVector selectedItems;
    if (coreSelection->isListBox() || coreSelection->isMenuList()) {
        // Set the list of selected items to an empty list; then verify that it worked.
        AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection);
        listBox->setSelectedChildren(selectedItems);
        listBox->selectedChildren(selectedItems);
        return !selectedItems.size();
    }
    return FALSE;
}
static AccessibilityObject* optionFromList(AtkSelection* selection, gint index)
{
    AccessibilityObject* coreSelection = core(selection);
    if (!coreSelection || index < 0)
        return 0;

    // Need to select the proper list object depending on the type.
    AccessibilityObject* listObject = listObjectForSelection(selection);
    if (!listObject)
        return 0;

    AccessibilityObject::AccessibilityChildrenVector options = listObject->children();
    if (index < static_cast<gint>(options.size()))
        return options.at(index).get();

    return 0;
}
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
{
    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
        static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders);
        unsigned rowCount = allRowHeaders.size();
        for (unsigned k = 0; k < rowCount; ++k) {
            pair<unsigned, unsigned> rowRange;
            AccessibilityTableCell* cell = static_cast<AccessibilityTableCell*>(allRowHeaders.at(k).get());
            cell->rowIndexRange(rowRange);
            if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second)
                return allRowHeaders[k]->wrapper();
        }
    }
    return 0;
}
static bool childrenContainUnrelatedControls(const AccessibilityObject::AccessibilityChildrenVector& children, AccessibilityObject* controlForLabel)
{
    if (!children.size())
        return false;

    for (const auto& child : children) {
        if (child->isControl()) {
            if (child == controlForLabel)
                continue;
            return true;
        }

        if (childrenContainUnrelatedControls(child->children(), controlForLabel))
            return true;
    }

    return false;
}
static gboolean webkitAccessibleSelectionClearSelection(AtkSelection* selection)
{
    g_return_val_if_fail(ATK_SELECTION(selection), FALSE);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), FALSE);

    AccessibilityObject* coreSelection = core(selection);
    if (!coreSelection)
        return FALSE;

    AccessibilityObject::AccessibilityChildrenVector selectedItems;
    if (coreSelection->isListBox() || coreSelection->isMenuList()) {
        // 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();
    }
    return FALSE;
}
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
{
    g_return_val_if_fail(ATK_TABLE(table), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);

    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
        toAccessibilityTable(accTable)->rowHeaders(allRowHeaders);
        unsigned rowCount = allRowHeaders.size();
        for (unsigned k = 0; k < rowCount; ++k) {
            pair<unsigned, unsigned> rowRange;
            AccessibilityTableCell* cell = toAccessibilityTableCell(allRowHeaders.at(k).get());
            cell->rowIndexRange(rowRange);
            if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second)
                return allRowHeaders[k]->wrapper();
        }
    }
    return 0;
}
static gboolean webkitAccessibleSelectionSelectAllSelection(AtkSelection* selection)
{
    g_return_val_if_fail(ATK_SELECTION(selection), FALSE);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), FALSE);

    AccessibilityObject* coreSelection = core(selection);
    if (!coreSelection || !coreSelection->isMultiSelectable())
        return FALSE;

    if (coreSelection->isListBox()) {
        const AccessibilityObject::AccessibilityChildrenVector& children = coreSelection->children();
        AccessibilityListBox* listBox = toAccessibilityListBox(coreSelection);
        listBox->setSelectedChildren(children);
        AccessibilityObject::AccessibilityChildrenVector selectedItems;
        listBox->selectedChildren(selectedItems);
        return selectedItems.size() == children.size();
    }

    return FALSE;
}
static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection)
{
    AccessibilityObject* coreSelection = core(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());
    }

    return 0;
}
예제 #23
0
static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject)
{
    guint16 interfaceMask = 0;

    // Component interface is always supported
    interfaceMask |= 1 << WAI_COMPONENT;

    AccessibilityRole role = coreObject->roleValue();

    // Action
    // As the implementation of the AtkAction interface is a very
    // basic one (just relays in executing the default action for each
    // 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;

    // Selection
    if (coreObject->isListBox() || coreObject->isMenuList())
        interfaceMask |= 1 << WAI_SELECTION;

    // Get renderer if available.
    RenderObject* renderer = 0;
    if (coreObject->isAccessibilityRenderObject())
        renderer = coreObject->renderer();

    // Hyperlink (links and embedded objects).
    if (coreObject->isLink() || (renderer && renderer->isReplaced()))
        interfaceMask |= 1 << WAI_HYPERLINK;

    // Text & Editable Text
    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;
            }

            // Add the TEXT interface for list items whose
            // first accessible child has a text renderer
            if (role == ListItemRole) {
                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;

    // Table
    if (role == TableRole)
        interfaceMask |= 1 << WAI_TABLE;

    // Document
    if (role == WebAreaRole)
        interfaceMask |= 1 << WAI_DOCUMENT;

    // Value
    if (role == SliderRole || role == SpinButtonRole || role == ScrollBarRole || role == ProgressIndicatorRole)
        interfaceMask |= 1 << WAI_VALUE;

#if ENABLE(INPUT_TYPE_COLOR)
    // Color type.
    if (role == ColorWellRole)
        interfaceMask |= 1 << WAI_TEXT;
#endif

    return interfaceMask;
}